1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

[AC-2206] Fix assigning Manage access to default collection (#3799)

* Fix assigning Manage access to default collection

The previous implementation did not work when creating an org as a
provider because the ownerId is null in OrganizationService.SignUp.
Added a null check and handled assigning access in ProviderService
instead.

* Tweaks
This commit is contained in:
Thomas Rittson
2024-02-15 00:41:51 +10:00
committed by GitHub
parent 97018e2501
commit a07aa8330c
6 changed files with 49 additions and 23 deletions

View File

@ -20,8 +20,17 @@ public interface IOrganizationService
Task AutoAddSeatsAsync(Organization organization, int seatsToAdd, DateTime? prorationDate = null);
Task<string> AdjustSeatsAsync(Guid organizationId, int seatAdjustment, DateTime? prorationDate = null);
Task VerifyBankAsync(Guid organizationId, int amount1, int amount2);
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup organizationSignup, bool provider = false);
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationLicense license, User owner,
/// <summary>
/// Create a new organization in a cloud environment
/// </summary>
/// <returns>A tuple containing the new organization, the initial organizationUser (if any) and the default collection (if any)</returns>
#nullable enable
Task<(Organization organization, OrganizationUser? organizationUser, Collection? defaultCollection)> SignUpAsync(OrganizationSignup organizationSignup, bool provider = false);
#nullable disable
/// <summary>
/// Create a new organization on a self-hosted instance
/// </summary>
Task<(Organization organization, OrganizationUser organizationUser)> SignUpAsync(OrganizationLicense license, User owner,
string ownerKey, string collectionName, string publicKey, string privateKey);
Task DeleteAsync(Organization organization);
Task EnableAsync(Guid organizationId, DateTime? expirationDate);

View File

@ -424,7 +424,7 @@ public class OrganizationService : IOrganizationService
/// <summary>
/// Create a new organization in a cloud environment
/// </summary>
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup,
public async Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignUpAsync(OrganizationSignup signup,
bool provider = false)
{
var plan = StaticStore.GetPlan(signup.Plan);
@ -552,7 +552,7 @@ public class OrganizationService : IOrganizationService
/// <summary>
/// Create a new organization on a self-hosted instance
/// </summary>
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(
public async Task<(Organization organization, OrganizationUser organizationUser)> SignUpAsync(
OrganizationLicense license, User owner, string ownerKey, string collectionName, string publicKey,
string privateKey)
{
@ -633,14 +633,14 @@ public class OrganizationService : IOrganizationService
Directory.CreateDirectory(dir);
await using var fs = new FileStream(Path.Combine(dir, $"{organization.Id}.json"), FileMode.Create);
await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented);
return result;
return (result.organization, result.organizationUser);
}
/// <summary>
/// Private helper method to create a new organization.
/// This is common code used by both the cloud and self-hosted methods.
/// </summary>
private async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(Organization organization,
private async Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignUpAsync(Organization organization,
Guid ownerId, string ownerKey, string collectionName, bool withPayment)
{
try
@ -655,6 +655,8 @@ public class OrganizationService : IOrganizationService
});
await _applicationCacheService.UpsertOrganizationAbilityAsync(organization);
// ownerId == default if the org is created by a provider - in this case it's created without an
// owner and the first owner is immediately invited afterwards
OrganizationUser orgUser = null;
if (ownerId != default)
{
@ -683,9 +685,10 @@ public class OrganizationService : IOrganizationService
await _pushNotificationService.PushSyncOrgKeysAsync(ownerId);
}
Collection defaultCollection = null;
if (!string.IsNullOrWhiteSpace(collectionName))
{
var defaultCollection = new Collection
defaultCollection = new Collection
{
Name = collectionName,
OrganizationId = organization.Id,
@ -695,7 +698,7 @@ public class OrganizationService : IOrganizationService
// If using Flexible Collections, give the owner Can Manage access over the default collection
List<CollectionAccessSelection> defaultOwnerAccess = null;
if (organization.FlexibleCollections)
if (orgUser != null && organization.FlexibleCollections)
{
defaultOwnerAccess =
[new CollectionAccessSelection { Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true }];
@ -704,7 +707,7 @@ public class OrganizationService : IOrganizationService
await _collectionRepository.CreateAsync(defaultCollection, null, defaultOwnerAccess);
}
return new Tuple<Organization, OrganizationUser>(organization, orgUser);
return (organization, orgUser, defaultCollection);
}
catch
{