mirror of
https://github.com/bitwarden/server
synced 2025-12-25 04:33:26 +00:00
* [AC-1174] Update SelectionReadOnlyRequestModel to use Guid for Id property * [AC-1174] Introduce initial bulk-access collection endpoint * [AC-1174] Introduce BulkAddCollectionAccessCommand and validation logic/tests * [AC-1174] Add CreateOrUpdateAccessMany method to CollectionRepository * [AC-1174] Add event logs for bulk add collection access command * [AC-1174] Add User_BumpAccountRevisionDateByCollectionIds and database migration script * [AC-1174] Implement EF repository method * [AC-1174] Improve null checks * [AC-1174] Remove unnecessary BulkCollectionAccessRequestModel helpers * [AC-1174] Add unit tests for new controller endpoint * [AC-1174] Fix formatting * [AC-1174] Remove comment * [AC-1174] Remove redundant organizationId parameter * [AC-1174] Ensure user and group Ids are distinct * [AC-1174] Cleanup tests based on PR feedback * [AC-1174] Formatting * [AC-1174] Update CollectionGroup alias in the sproc * [AC-1174] Add some additional comments to SQL sproc * [AC-1174] Add comment explaining additional SaveChangesAsync call --------- Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
96 lines
3.5 KiB
C#
96 lines
3.5 KiB
C#
using Bit.Core.Entities;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Exceptions;
|
|
using Bit.Core.Models.Data;
|
|
using Bit.Core.OrganizationFeatures.OrganizationCollections.Interfaces;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Services;
|
|
|
|
namespace Bit.Core.OrganizationFeatures.OrganizationCollections;
|
|
|
|
public class BulkAddCollectionAccessCommand : IBulkAddCollectionAccessCommand
|
|
{
|
|
private readonly ICollectionRepository _collectionRepository;
|
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
|
private readonly IGroupRepository _groupRepository;
|
|
private readonly IEventService _eventService;
|
|
|
|
public BulkAddCollectionAccessCommand(
|
|
ICollectionRepository collectionRepository,
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
IGroupRepository groupRepository,
|
|
IEventService eventService)
|
|
{
|
|
_collectionRepository = collectionRepository;
|
|
_organizationUserRepository = organizationUserRepository;
|
|
_groupRepository = groupRepository;
|
|
_eventService = eventService;
|
|
}
|
|
|
|
public async Task AddAccessAsync(ICollection<Collection> collections,
|
|
ICollection<CollectionAccessSelection> users,
|
|
ICollection<CollectionAccessSelection> groups)
|
|
{
|
|
await ValidateRequestAsync(collections, users, groups);
|
|
|
|
await _collectionRepository.CreateOrUpdateAccessForManyAsync(
|
|
collections.First().OrganizationId,
|
|
collections.Select(c => c.Id),
|
|
users,
|
|
groups
|
|
);
|
|
|
|
await _eventService.LogCollectionEventsAsync(collections.Select(c =>
|
|
(c, EventType.Collection_Updated, (DateTime?)DateTime.UtcNow)));
|
|
}
|
|
|
|
private async Task ValidateRequestAsync(ICollection<Collection> collections, ICollection<CollectionAccessSelection> usersAccess, ICollection<CollectionAccessSelection> groupsAccess)
|
|
{
|
|
if (collections == null || collections.Count == 0)
|
|
{
|
|
throw new BadRequestException("No collections were provided.");
|
|
}
|
|
|
|
var orgId = collections.First().OrganizationId;
|
|
|
|
if (collections.Any(c => c.OrganizationId != orgId))
|
|
{
|
|
throw new BadRequestException("All collections must belong to the same organization.");
|
|
}
|
|
|
|
var collectionUserIds = usersAccess?.Select(u => u.Id).Distinct().ToList();
|
|
|
|
if (collectionUserIds is { Count: > 0 })
|
|
{
|
|
var users = await _organizationUserRepository.GetManyAsync(collectionUserIds);
|
|
|
|
if (users.Count != collectionUserIds.Count)
|
|
{
|
|
throw new BadRequestException("One or more users do not exist.");
|
|
}
|
|
|
|
if (users.Any(u => u.OrganizationId != orgId))
|
|
{
|
|
throw new BadRequestException("One or more users do not belong to the same organization as the collection being assigned.");
|
|
}
|
|
}
|
|
|
|
var collectionGroupIds = groupsAccess?.Select(g => g.Id).Distinct().ToList();
|
|
|
|
if (collectionGroupIds is { Count: > 0 })
|
|
{
|
|
var groups = await _groupRepository.GetManyByManyIds(collectionGroupIds);
|
|
|
|
if (groups.Count != collectionGroupIds.Count)
|
|
{
|
|
throw new BadRequestException("One or more groups do not exist.");
|
|
}
|
|
|
|
if (groups.Any(g => g.OrganizationId != orgId))
|
|
{
|
|
throw new BadRequestException("One or more groups do not belong to the same organization as the collection being assigned.");
|
|
}
|
|
}
|
|
}
|
|
}
|