using Bit.Core.Enums; using Bit.Core.Utilities; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.RustSDK; using Bit.Seeder.Data; using Bit.Seeder.Data.Enums; using Bit.Seeder.Factories; using LinqToDB.EntityFrameworkCore; namespace Bit.Seeder.Recipes; /// /// Creates collections for seeding organization vaults. /// public class CollectionsRecipe(DatabaseContext db, RustSdkService sdkService) { private readonly CollectionSeeder _collectionSeeder = new(sdkService); /// /// Creates collections from an organizational structure (e.g., Traditional departments, Spotify tribes). /// Collection names are properly encrypted. /// public List AddFromStructure( Guid organizationId, string orgKeyBase64, OrgStructureModel model, List organizationUserIds, int maxUsersWithRelationships = 1000) { var structure = OrgStructures.GetStructure(model); var collections = structure.Units .Select(unit => _collectionSeeder.CreateCollection(organizationId, orgKeyBase64, unit.Name)) .ToList(); db.BulkCopy(collections); if (collections.Count > 0 && organizationUserIds.Count > 0 && maxUsersWithRelationships > 0) { var collectionUsers = BuildCollectionUserRelationships(collections, organizationUserIds, maxUsersWithRelationships); db.BulkCopy(collectionUsers); } return collections.Select(c => c.Id).ToList(); } /// /// Adds generic numbered collections (unencrypted names - use AddFromStructure for realistic data). /// public List AddToOrganization(Guid organizationId, int collections, List organizationUserIds, int maxUsersWithRelationships = 1000) { var collectionList = Enumerable.Range(0, collections) .Select(i => new Core.Entities.Collection { Id = CoreHelpers.GenerateComb(), OrganizationId = organizationId, Name = $"Collection {i + 1}", Type = CollectionType.SharedCollection, CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }) .ToList(); db.BulkCopy(collectionList); if (collectionList.Count > 0 && organizationUserIds.Count > 0 && maxUsersWithRelationships > 0) { var collectionUsers = BuildCollectionUserRelationships(collectionList, organizationUserIds, maxUsersWithRelationships); db.BulkCopy(collectionUsers); } return collectionList.Select(c => c.Id).ToList(); } /// /// Creates user-to-collection relationships with varied assignment patterns. /// Each user gets 1-3 collections (cycling). First collection has Manage rights. /// private static List BuildCollectionUserRelationships( List collections, List organizationUserIds, int maxUsersWithRelationships) { return organizationUserIds .Take(maxUsersWithRelationships) .SelectMany((orgUserId, userIndex) => { var collectionCount = (userIndex % 3) + 1; // Cycles through 1, 2, or 3 return Enumerable.Range(0, collectionCount) .Select(j => new Core.Entities.CollectionUser { CollectionId = collections[(userIndex + j) % collections.Count].Id, OrganizationUserId = orgUserId, ReadOnly = j > 0, HidePasswords = false, Manage = j == 0 }); }) .ToList(); } }