mirror of
https://github.com/bitwarden/server.git
synced 2025-06-24 12:48:48 -05:00
[PM-22503] Fix manage cipher permission (#5972)
* Added new tests to validate that the ciphers are being grouped and filtered correctly when assigned to multiple collections and changing order of grouping properties.
This commit is contained in:
parent
cdfe51f9d6
commit
d2410747d0
@ -98,7 +98,10 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
|||||||
|
|
||||||
return results
|
return results
|
||||||
.GroupBy(c => c.Id)
|
.GroupBy(c => c.Id)
|
||||||
.Select(g => g.OrderByDescending(og => og.Edit).ThenByDescending(og => og.ViewPassword).First())
|
.Select(g =>
|
||||||
|
g.OrderByDescending(og => og.Manage)
|
||||||
|
.ThenByDescending(og => og.Edit)
|
||||||
|
.ThenByDescending(og => og.ViewPassword).First())
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,7 +457,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
|||||||
using (var scope = ServiceScopeFactory.CreateScope())
|
using (var scope = ServiceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
var dbContext = GetDatabaseContext(scope);
|
var dbContext = GetDatabaseContext(scope);
|
||||||
IQueryable<CipherDetails> cipherDetailsView = withOrganizations ?
|
var cipherDetailsView = withOrganizations ?
|
||||||
new UserCipherDetailsQuery(userId).Run(dbContext) :
|
new UserCipherDetailsQuery(userId).Run(dbContext) :
|
||||||
new CipherDetailsQuery(userId).Run(dbContext);
|
new CipherDetailsQuery(userId).Run(dbContext);
|
||||||
if (!withOrganizations)
|
if (!withOrganizations)
|
||||||
@ -485,8 +485,15 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
|||||||
Key = c.Key
|
Key = c.Key
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var ciphers = await cipherDetailsView.ToListAsync();
|
var ciphers = await cipherDetailsView.ToListAsync();
|
||||||
return ciphers;
|
|
||||||
|
return ciphers.GroupBy(c => c.Id)
|
||||||
|
.Select(g => g.OrderByDescending(c => c.Manage)
|
||||||
|
.ThenByDescending(c => c.Edit)
|
||||||
|
.ThenByDescending(c => c.ViewPassword)
|
||||||
|
.First())
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,6 +571,65 @@ public class CipherRepositoryTests
|
|||||||
Assert.True(personalDetails.Manage, "Personal ciphers should always have Manage permission");
|
Assert.True(personalDetails.Manage, "Personal ciphers should always have Manage permission");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DatabaseTheory, DatabaseData]
|
||||||
|
public async Task GetManyByUserIdAsync_WhenOneCipherIsAssignedToTwoCollectionsWithDifferentPermissions_MostPrivilegedAccessIsReturnedOnTheCipher(
|
||||||
|
ICipherRepository cipherRepository,
|
||||||
|
IUserRepository userRepository,
|
||||||
|
ICollectionCipherRepository collectionCipherRepository,
|
||||||
|
ICollectionRepository collectionRepository,
|
||||||
|
IOrganizationRepository organizationRepository,
|
||||||
|
IOrganizationUserRepository organizationUserRepository)
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
var (user, organization, orgUser) = await CreateTestUserAndOrganization(userRepository, organizationRepository, organizationUserRepository);
|
||||||
|
|
||||||
|
var cipher = await cipherRepository.CreateAsync(new Cipher
|
||||||
|
{
|
||||||
|
Type = CipherType.Login,
|
||||||
|
OrganizationId = organization.Id,
|
||||||
|
Data = ""
|
||||||
|
});
|
||||||
|
|
||||||
|
var managedPermissionsCollection = await collectionRepository.CreateAsync(new Collection
|
||||||
|
{
|
||||||
|
Name = "Managed",
|
||||||
|
OrganizationId = organization.Id
|
||||||
|
});
|
||||||
|
|
||||||
|
var unmanagedPermissionsCollection = await collectionRepository.CreateAsync(new Collection
|
||||||
|
{
|
||||||
|
Name = "Unmanaged",
|
||||||
|
OrganizationId = organization.Id
|
||||||
|
});
|
||||||
|
await collectionCipherRepository.UpdateCollectionsForAdminAsync(cipher.Id, organization.Id,
|
||||||
|
[managedPermissionsCollection.Id, unmanagedPermissionsCollection.Id]);
|
||||||
|
|
||||||
|
await collectionRepository.UpdateUsersAsync(managedPermissionsCollection.Id, new List<CollectionAccessSelection>
|
||||||
|
{
|
||||||
|
new() { Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true }
|
||||||
|
});
|
||||||
|
|
||||||
|
await collectionRepository.UpdateUsersAsync(unmanagedPermissionsCollection.Id, new List<CollectionAccessSelection>
|
||||||
|
{
|
||||||
|
new() { Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = false }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var ciphers = await cipherRepository.GetManyByUserIdAsync(user.Id);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(ciphers);
|
||||||
|
var deletableCipher = ciphers.SingleOrDefault(x => x.Id == cipher.Id);
|
||||||
|
Assert.NotNull(deletableCipher);
|
||||||
|
Assert.True(deletableCipher.Manage);
|
||||||
|
|
||||||
|
// Annul
|
||||||
|
await cipherRepository.DeleteAsync(cipher);
|
||||||
|
await organizationUserRepository.DeleteAsync(orgUser);
|
||||||
|
await organizationRepository.DeleteAsync(organization);
|
||||||
|
await userRepository.DeleteAsync(user);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<(User user, Organization org, OrganizationUser orgUser)> CreateTestUserAndOrganization(
|
private async Task<(User user, Organization org, OrganizationUser orgUser)> CreateTestUserAndOrganization(
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user