1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52:49 -05:00

renaming subvault => collection

This commit is contained in:
Kyle Spearrin
2017-04-27 09:19:30 -04:00
parent 2340369d56
commit c6ac82dadd
87 changed files with 493 additions and 493 deletions

View File

@ -64,7 +64,7 @@ namespace Bit.Core.Models.Api
public class CipherShareRequestModel : IValidatableObject
{
[Required]
public IEnumerable<string> SubvaultIds { get; set; }
public IEnumerable<string> CollectionIds { get; set; }
[Required]
public CipherRequestModel Cipher { get; set; }
@ -76,17 +76,17 @@ namespace Bit.Core.Models.Api
new string[] { nameof(Cipher.OrganizationId) });
}
if(!SubvaultIds?.Any() ?? false)
if(!CollectionIds?.Any() ?? false)
{
yield return new ValidationResult("You must select at least one subvault.",
new string[] { nameof(SubvaultIds) });
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
}
}
}
public class CipherSubvaultsRequestModel
public class CipherCollectionsRequestModel
{
[Required]
public IEnumerable<string> SubvaultIds { get; set; }
public IEnumerable<string> CollectionIds { get; set; }
}
}

View File

@ -12,8 +12,8 @@ namespace Bit.Core.Models.Api
public string Email { get; set; }
[Required]
public Enums.OrganizationUserType? Type { get; set; }
public bool AccessAllSubvaults { get; set; }
public IEnumerable<OrganizationUserSubvaultRequestModel> Subvaults { get; set; }
public bool AccessAllCollections { get; set; }
public IEnumerable<OrganizationUserCollectionRequestModel> Collections { get; set; }
}
public class OrganizationUserAcceptRequestModel
@ -32,32 +32,32 @@ namespace Bit.Core.Models.Api
{
[Required]
public Enums.OrganizationUserType? Type { get; set; }
public bool AccessAllSubvaults { get; set; }
public IEnumerable<OrganizationUserSubvaultRequestModel> Subvaults { get; set; }
public bool AccessAllCollections { get; set; }
public IEnumerable<OrganizationUserCollectionRequestModel> Collections { get; set; }
public OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
existingUser.Type = Type.Value;
existingUser.AccessAllSubvaults = AccessAllSubvaults;
existingUser.AccessAllCollections = AccessAllCollections;
return existingUser;
}
}
public class OrganizationUserSubvaultRequestModel
public class OrganizationUserCollectionRequestModel
{
[Required]
public string SubvaultId { get; set; }
public string CollectionId { get; set; }
public bool ReadOnly { get; set; }
public SubvaultUser ToSubvaultUser()
public CollectionUser ToCollectionUser()
{
var subvault = new SubvaultUser
var collection = new CollectionUser
{
ReadOnly = ReadOnly,
SubvaultId = new Guid(SubvaultId)
CollectionId = new Guid(CollectionId)
};
return subvault;
return collection;
}
}
}

View File

@ -6,25 +6,25 @@ using Newtonsoft.Json;
namespace Bit.Core.Models.Api
{
public class SubvaultRequestModel
public class CollectionRequestModel
{
[Required]
[EncryptedString]
[StringLength(300)]
public string Name { get; set; }
public Subvault ToSubvault(Guid orgId)
public Collection ToCollection(Guid orgId)
{
return ToSubvault(new Subvault
return ToCollection(new Collection
{
OrganizationId = orgId
});
}
public Subvault ToSubvault(Subvault existingSubvault)
public Collection ToCollection(Collection existingCollection)
{
existingSubvault.Name = Name;
return existingSubvault;
existingCollection.Name = Name;
return existingCollection;
}
}
}

View File

@ -5,29 +5,29 @@ using System.Linq;
namespace Bit.Core.Models.Api
{
public class SubvaultUserSubvaultRequestModel
public class CollectionUserCollectionRequestModel
{
public string UserId { get; set; }
public IEnumerable<Subvault> Subvaults { get; set; }
public IEnumerable<Collection> Collections { get; set; }
public IEnumerable<SubvaultUser> ToSubvaultUsers()
public IEnumerable<CollectionUser> ToCollectionUsers()
{
return Subvaults.Select(s => new SubvaultUser
return Collections.Select(s => new CollectionUser
{
OrganizationUserId = new Guid(UserId),
SubvaultId = new Guid(s.SubvaultId),
CollectionId = new Guid(s.CollectionId),
ReadOnly = s.ReadOnly
});
}
public class Subvault
public class Collection
{
public string SubvaultId { get; set; }
public string CollectionId { get; set; }
public bool ReadOnly { get; set; }
}
}
public class SubvaultUserUserRequestModel
public class CollectionUserUserRequestModel
{
public string UserId { get; set; }
public bool ReadOnly { get; set; }

View File

@ -74,52 +74,52 @@ namespace Bit.Core.Models.Api
public class CipherDetailsResponseModel : CipherResponseModel
{
public CipherDetailsResponseModel(CipherDetails cipher,
IDictionary<Guid, IGrouping<Guid, SubvaultCipher>> subvaultCiphers, string obj = "cipherDetails")
IDictionary<Guid, IGrouping<Guid, CollectionCipher>> collectionCiphers, string obj = "cipherDetails")
: base(cipher, obj)
{
if(subvaultCiphers.ContainsKey(cipher.Id))
if(collectionCiphers.ContainsKey(cipher.Id))
{
SubvaultIds = subvaultCiphers[cipher.Id].Select(s => s.SubvaultId);
CollectionIds = collectionCiphers[cipher.Id].Select(s => s.CollectionId);
}
else
{
SubvaultIds = new Guid[] { };
CollectionIds = new Guid[] { };
}
}
public CipherDetailsResponseModel(CipherDetails cipher, IEnumerable<SubvaultCipher> subvaultCiphers,
public CipherDetailsResponseModel(CipherDetails cipher, IEnumerable<CollectionCipher> collectionCiphers,
string obj = "cipherDetails")
: base(cipher, obj)
{
SubvaultIds = subvaultCiphers.Select(s => s.SubvaultId);
CollectionIds = collectionCiphers.Select(s => s.CollectionId);
}
public IEnumerable<Guid> SubvaultIds { get; set; }
public IEnumerable<Guid> CollectionIds { get; set; }
}
public class CipherMiniDetailsResponseModel : CipherMiniResponseModel
{
public CipherMiniDetailsResponseModel(Cipher cipher,
IDictionary<Guid, IGrouping<Guid, SubvaultCipher>> subvaultCiphers, string obj = "cipherMiniDetails")
IDictionary<Guid, IGrouping<Guid, CollectionCipher>> collectionCiphers, string obj = "cipherMiniDetails")
: base(cipher, obj)
{
if(subvaultCiphers.ContainsKey(cipher.Id))
if(collectionCiphers.ContainsKey(cipher.Id))
{
SubvaultIds = subvaultCiphers[cipher.Id].Select(s => s.SubvaultId);
CollectionIds = collectionCiphers[cipher.Id].Select(s => s.CollectionId);
}
else
{
SubvaultIds = new Guid[] { };
CollectionIds = new Guid[] { };
}
}
public IEnumerable<Guid> SubvaultIds { get; set; }
public IEnumerable<Guid> CollectionIds { get; set; }
}
public class CipherFullDetailsResponseModel : CipherDetailsResponseModel
{
public CipherFullDetailsResponseModel(CipherFullDetails cipher, IEnumerable<SubvaultCipher> subvaultCiphers)
: base(cipher, subvaultCiphers, "cipherFullDetails")
public CipherFullDetailsResponseModel(CipherFullDetails cipher, IEnumerable<CollectionCipher> collectionCiphers)
: base(cipher, collectionCiphers, "cipherFullDetails")
{
Edit = cipher.Edit;
}

View File

@ -22,7 +22,7 @@ namespace Bit.Core.Models.Api
Email = organizationUser.Email;
Type = organizationUser.Type;
Status = organizationUser.Status;
AccessAllSubvaults = organizationUser.AccessAllSubvaults;
AccessAllCollections = organizationUser.AccessAllCollections;
}
public string Id { get; set; }
@ -31,19 +31,19 @@ namespace Bit.Core.Models.Api
public string Email { get; set; }
public OrganizationUserType Type { get; set; }
public OrganizationUserStatusType Status { get; set; }
public bool AccessAllSubvaults { get; set; }
public bool AccessAllCollections { get; set; }
}
public class OrganizationUserDetailsResponseModel : OrganizationUserResponseModel
{
public OrganizationUserDetailsResponseModel(OrganizationUserUserDetails organizationUser,
IEnumerable<SubvaultUserSubvaultDetails> subvaults)
IEnumerable<CollectionUserCollectionDetails> collections)
: base(organizationUser, "organizationUserDetails")
{
Subvaults = new ListResponseModel<OrganizationUserSubvaultResponseModel>(
subvaults.Select(s => new OrganizationUserSubvaultResponseModel(s)));
Collections = new ListResponseModel<OrganizationUserCollectionResponseModel>(
collections.Select(s => new OrganizationUserCollectionResponseModel(s)));
}
public ListResponseModel<OrganizationUserSubvaultResponseModel> Subvaults { get; set; }
public ListResponseModel<OrganizationUserCollectionResponseModel> Collections { get; set; }
}
}

View File

@ -3,10 +3,10 @@ using Bit.Core.Models.Data;
namespace Bit.Core.Models.Api
{
public class OrganizationUserSubvaultResponseModel : ResponseModel
public class OrganizationUserCollectionResponseModel : ResponseModel
{
public OrganizationUserSubvaultResponseModel(SubvaultUserSubvaultDetails details,
string obj = "organizationUserSubvault")
public OrganizationUserCollectionResponseModel(CollectionUserCollectionDetails details,
string obj = "organizationUserCollection")
: base(obj)
{
if(details == null)
@ -16,13 +16,13 @@ namespace Bit.Core.Models.Api
Id = details.Id.ToString();
Name = details.Name;
SubvaultId = details.SubvaultId.ToString();
CollectionId = details.CollectionId.ToString();
ReadOnly = details.ReadOnly;
}
public string Id { get; set; }
public string Name { get; set; }
public string SubvaultId { get; set; }
public string CollectionId { get; set; }
public bool ReadOnly { get; set; }
}
}

View File

@ -3,19 +3,19 @@ using Bit.Core.Models.Table;
namespace Bit.Core.Models.Api
{
public class SubvaultResponseModel : ResponseModel
public class CollectionResponseModel : ResponseModel
{
public SubvaultResponseModel(Subvault subvault)
: base("subvault")
public CollectionResponseModel(Collection collection)
: base("collection")
{
if(subvault == null)
if(collection == null)
{
throw new ArgumentNullException(nameof(subvault));
throw new ArgumentNullException(nameof(collection));
}
Id = subvault.Id.ToString();
OrganizationId = subvault.OrganizationId.ToString();
Name = subvault.Name;
Id = collection.Id.ToString();
OrganizationId = collection.OrganizationId.ToString();
Name = collection.Name;
}
public string Id { get; set; }

View File

@ -5,31 +5,31 @@ using Bit.Core.Enums;
namespace Bit.Core.Models.Api
{
public class SubvaultUserResponseModel : ResponseModel
public class CollectionUserResponseModel : ResponseModel
{
public SubvaultUserResponseModel(SubvaultUserUserDetails subvaultUser)
: base("subvaultUser")
public CollectionUserResponseModel(CollectionUserUserDetails collectionUser)
: base("collectionUser")
{
if(subvaultUser == null)
if(collectionUser == null)
{
throw new ArgumentNullException(nameof(subvaultUser));
throw new ArgumentNullException(nameof(collectionUser));
}
Id = subvaultUser.Id?.ToString();
OrganizationUserId = subvaultUser.OrganizationUserId.ToString();
SubvaultId = subvaultUser.SubvaultId?.ToString();
AccessAllSubvaults = subvaultUser.AccessAllSubvaults;
Name = subvaultUser.Name;
Email = subvaultUser.Email;
Type = subvaultUser.Type;
Status = subvaultUser.Status;
ReadOnly = subvaultUser.ReadOnly;
Id = collectionUser.Id?.ToString();
OrganizationUserId = collectionUser.OrganizationUserId.ToString();
CollectionId = collectionUser.CollectionId?.ToString();
AccessAllCollections = collectionUser.AccessAllCollections;
Name = collectionUser.Name;
Email = collectionUser.Email;
Type = collectionUser.Type;
Status = collectionUser.Status;
ReadOnly = collectionUser.ReadOnly;
}
public string Id { get; set; }
public string OrganizationUserId { get; set; }
public string SubvaultId { get; set; }
public bool AccessAllSubvaults { get; set; }
public string CollectionId { get; set; }
public bool AccessAllCollections { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public OrganizationUserType Type { get; set; }

View File

@ -11,6 +11,6 @@ namespace Bit.Core.Models.Data
public string Email { get; set; }
public Enums.OrganizationUserStatusType Status { get; set; }
public Enums.OrganizationUserType Type { get; set; }
public bool AccessAllSubvaults { get; set; }
public bool AccessAllCollections { get; set; }
}
}

View File

@ -2,12 +2,12 @@
namespace Bit.Core.Models.Data
{
public class SubvaultUserSubvaultDetails
public class CollectionUserCollectionDetails
{
public Guid Id { get; set; }
public Guid OrganizationUserId { get; set; }
public string Name { get; set; }
public Guid SubvaultId { get; set; }
public Guid CollectionId { get; set; }
public bool ReadOnly { get; set; }
}
}

View File

@ -2,12 +2,12 @@
namespace Bit.Core.Models.Data
{
public class SubvaultUserUserDetails
public class CollectionUserUserDetails
{
public Guid? Id { get; set; }
public Guid OrganizationUserId { get; set; }
public Guid? SubvaultId { get; set; }
public bool AccessAllSubvaults { get; set; }
public Guid? CollectionId { get; set; }
public bool AccessAllCollections { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public Enums.OrganizationUserStatusType Status { get; set; }

View File

@ -13,7 +13,7 @@ namespace Bit.Core.Models.StaticStore
public short? MaxAdditionalSeats { get; set; }
public decimal BasePrice { get; set; }
public decimal SeatPrice { get; set; }
public short? MaxSubvaults { get; set; }
public short? MaxCollections { get; set; }
public int UpgradeSortOrder { get; set; }
public bool Disabled { get; set; }
public int? TrialPeriodDays { get; set; }

View File

@ -13,7 +13,7 @@ namespace Bit.Core.Models.Table
public string Plan { get; set; }
public PlanType PlanType { get; set; }
public short? Seats { get; set; }
public short? MaxSubvaults { get; set; }
public short? MaxCollections { get; set; }
public string StripeCustomerId { get; set; }
public string StripeSubscriptionId { get; set; }
public bool Enabled { get; set; } = true;

View File

@ -13,7 +13,7 @@ namespace Bit.Core.Models.Table
public string Key { get; set; }
public OrganizationUserStatusType Status { get; set; }
public OrganizationUserType Type { get; set; }
public bool AccessAllSubvaults { get; set; }
public bool AccessAllCollections { get; set; }
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;

View File

@ -3,7 +3,7 @@ using Bit.Core.Utilities;
namespace Bit.Core.Models.Table
{
public class Subvault : IDataObject<Guid>
public class Collection : IDataObject<Guid>
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }

View File

@ -2,9 +2,9 @@
namespace Bit.Core.Models.Table
{
public class SubvaultCipher
public class CollectionCipher
{
public Guid SubvaultId { get; set; }
public Guid CollectionId { get; set; }
public Guid CipherId { get; set; }
}
}

View File

@ -3,10 +3,10 @@ using Bit.Core.Utilities;
namespace Bit.Core.Models.Table
{
public class SubvaultUser : IDataObject<Guid>
public class CollectionUser : IDataObject<Guid>
{
public Guid Id { get; set; }
public Guid SubvaultId { get; set; }
public Guid CollectionId { get; set; }
public Guid OrganizationUserId { get; set; }
public bool ReadOnly { get; set; }
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;

View File

@ -11,13 +11,13 @@ namespace Bit.Core.Repositories
Task<CipherDetails> GetByIdAsync(Guid id, Guid userId);
Task<CipherFullDetails> GetFullDetailsByIdAsync(Guid id, Guid userId);
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId);
Task<ICollection<CipherDetails>> GetManyByUserIdHasSubvaultsAsync(Guid userId);
Task<ICollection<CipherDetails>> GetManyByUserIdHasCollectionsAsync(Guid userId);
Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<CipherDetails>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId);
Task CreateAsync(CipherDetails cipher);
Task ReplaceAsync(CipherDetails cipher);
Task UpsertAsync(CipherDetails cipher);
Task ReplaceAsync(Cipher obj, IEnumerable<Guid> subvaultIds);
Task ReplaceAsync(Cipher obj, IEnumerable<Guid> collectionIds);
Task UpdatePartialAsync(Guid id, Guid userId, Guid? folderId, bool favorite);
Task UpdateUserEmailPasswordAndCiphersAsync(User user, IEnumerable<Cipher> ciphers, IEnumerable<Folder> folders);
Task CreateAsync(IEnumerable<Cipher> ciphers, IEnumerable<Folder> folders);

View File

@ -15,7 +15,7 @@ namespace Bit.Core.Repositories
Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type);
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email);
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, Guid userId);
Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>> GetDetailsByIdAsync(Guid id);
Task<Tuple<OrganizationUserUserDetails, ICollection<CollectionUserCollectionDetails>>> GetDetailsByIdAsync(Guid id);
Task<ICollection<OrganizationUserUserDetails>> GetManyDetailsByOrganizationAsync(Guid organizationId);
Task<ICollection<OrganizationUserOrganizationDetails>> GetManyDetailsByUserAsync(Guid userId,
OrganizationUserStatusType? status = null);

View File

@ -5,12 +5,12 @@ using System.Collections.Generic;
namespace Bit.Core.Repositories
{
public interface ISubvaultCipherRepository
public interface ICollectionCipherRepository
{
Task<ICollection<SubvaultCipher>> GetManyByUserIdAsync(Guid userId);
Task<ICollection<SubvaultCipher>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId);
Task UpdateSubvaultsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> subvaultIds);
Task UpdateSubvaultsForAdminAsync(Guid cipherId, Guid organizationId, IEnumerable<Guid> subvaultIds);
Task<ICollection<CollectionCipher>> GetManyByUserIdAsync(Guid userId);
Task<ICollection<CollectionCipher>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<CollectionCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId);
Task UpdateCollectionsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> collectionIds);
Task UpdateCollectionsForAdminAsync(Guid cipherId, Guid organizationId, IEnumerable<Guid> collectionIds);
}
}

View File

@ -5,11 +5,11 @@ using System.Collections.Generic;
namespace Bit.Core.Repositories
{
public interface ISubvaultRepository : IRepository<Subvault, Guid>
public interface ICollectionRepository : IRepository<Collection, Guid>
{
Task<int> GetCountByOrganizationIdAsync(Guid organizationId);
Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<Subvault>> GetManyByUserIdAsync(Guid userId);
Task<ICollection<Collection>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<Collection>> GetManyByUserIdAsync(Guid userId);
}
}

View File

@ -6,11 +6,11 @@ using Bit.Core.Models.Data;
namespace Bit.Core.Repositories
{
public interface ISubvaultUserRepository : IRepository<SubvaultUser, Guid>
public interface ICollectionUserRepository : IRepository<CollectionUser, Guid>
{
Task<ICollection<SubvaultUser>> GetManyByOrganizationUserIdAsync(Guid orgUserId);
Task<ICollection<SubvaultUserSubvaultDetails>> GetManyDetailsByUserIdAsync(Guid userId);
Task<ICollection<SubvaultUserUserDetails>> GetManyDetailsBySubvaultIdAsync(Guid subvaultId);
Task<ICollection<CollectionUser>> GetManyByOrganizationUserIdAsync(Guid orgUserId);
Task<ICollection<CollectionUserCollectionDetails>> GetManyDetailsByUserIdAsync(Guid userId);
Task<ICollection<CollectionUserUserDetails>> GetManyDetailsByCollectionIdAsync(Guid collectionId);
Task<bool> GetCanEditByUserIdCipherIdAsync(Guid userId, Guid cipherId);
}
}

View File

@ -62,12 +62,12 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<CipherDetails>> GetManyByUserIdHasSubvaultsAsync(Guid userId)
public async Task<ICollection<CipherDetails>> GetManyByUserIdHasCollectionsAsync(Guid userId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<CipherDetails>(
$"[{Schema}].[CipherDetails_ReadByUserIdHasSubvault]",
$"[{Schema}].[CipherDetails_ReadByUserIdHasCollection]",
new { UserId = userId },
commandType: CommandType.StoredProcedure);
@ -142,16 +142,16 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task ReplaceAsync(Cipher obj, IEnumerable<Guid> subvaultIds)
public async Task ReplaceAsync(Cipher obj, IEnumerable<Guid> collectionIds)
{
var objWithSubvaults = JsonConvert.DeserializeObject<CipherWithSubvaults>(JsonConvert.SerializeObject(obj));
objWithSubvaults.SubvaultIds = subvaultIds.ToGuidIdArrayTVP();
var objWithCollections = JsonConvert.DeserializeObject<CipherWithCollections>(JsonConvert.SerializeObject(obj));
objWithCollections.CollectionIds = collectionIds.ToGuidIdArrayTVP();
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.ExecuteAsync(
$"[{Schema}].[Cipher_UpdateWithSubvaults]",
objWithSubvaults,
$"[{Schema}].[Cipher_UpdateWithCollections]",
objWithCollections,
commandType: CommandType.StoredProcedure);
}
}
@ -419,9 +419,9 @@ namespace Bit.Core.Repositories.SqlServer
return foldersTable;
}
public class CipherWithSubvaults : Cipher
public class CipherWithCollections : Cipher
{
public DataTable SubvaultIds { get; set; }
public DataTable CollectionIds { get; set; }
}
}
}

View File

@ -100,7 +100,7 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>> GetDetailsByIdAsync(Guid id)
public async Task<Tuple<OrganizationUserUserDetails, ICollection<CollectionUserCollectionDetails>>> GetDetailsByIdAsync(Guid id)
{
using(var connection = new SqlConnection(ConnectionString))
{
@ -110,8 +110,8 @@ namespace Bit.Core.Repositories.SqlServer
commandType: CommandType.StoredProcedure);
var user = (await results.ReadAsync<OrganizationUserUserDetails>()).SingleOrDefault();
var subvaults = (await results.ReadAsync<SubvaultUserSubvaultDetails>()).ToList();
return new Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>(user, subvaults);
var collections = (await results.ReadAsync<CollectionUserCollectionDetails>()).ToList();
return new Tuple<OrganizationUserUserDetails, ICollection<CollectionUserCollectionDetails>>(user, collections);
}
}

View File

@ -10,22 +10,22 @@ using Bit.Core.Utilities;
namespace Bit.Core.Repositories.SqlServer
{
public class SubvaultCipherRepository : BaseRepository, ISubvaultCipherRepository
public class CollectionCipherRepository : BaseRepository, ICollectionCipherRepository
{
public SubvaultCipherRepository(GlobalSettings globalSettings)
public CollectionCipherRepository(GlobalSettings globalSettings)
: this(globalSettings.SqlServer.ConnectionString)
{ }
public SubvaultCipherRepository(string connectionString)
public CollectionCipherRepository(string connectionString)
: base(connectionString)
{ }
public async Task<ICollection<SubvaultCipher>> GetManyByUserIdAsync(Guid userId)
public async Task<ICollection<CollectionCipher>> GetManyByUserIdAsync(Guid userId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultCipher>(
"[dbo].[SubvaultCipher_ReadByUserId]",
var results = await connection.QueryAsync<CollectionCipher>(
"[dbo].[CollectionCipher_ReadByUserId]",
new { UserId = userId },
commandType: CommandType.StoredProcedure);
@ -33,12 +33,12 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<SubvaultCipher>> GetManyByOrganizationIdAsync(Guid organizationId)
public async Task<ICollection<CollectionCipher>> GetManyByOrganizationIdAsync(Guid organizationId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultCipher>(
"[dbo].[SubvaultCipher_ReadByOrganizationId]",
var results = await connection.QueryAsync<CollectionCipher>(
"[dbo].[CollectionCipher_ReadByOrganizationId]",
new { OrganizationId = organizationId },
commandType: CommandType.StoredProcedure);
@ -46,12 +46,12 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId)
public async Task<ICollection<CollectionCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultCipher>(
"[dbo].[SubvaultCipher_ReadByUserIdCipherId]",
var results = await connection.QueryAsync<CollectionCipher>(
"[dbo].[CollectionCipher_ReadByUserIdCipherId]",
new { UserId = userId, CipherId = cipherId },
commandType: CommandType.StoredProcedure);
@ -59,24 +59,24 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task UpdateSubvaultsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> subvaultIds)
public async Task UpdateCollectionsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> collectionIds)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.ExecuteAsync(
"[dbo].[SubvaultCipher_UpdateSubvaults]",
new { CipherId = cipherId, UserId = userId, SubvaultIds = subvaultIds.ToGuidIdArrayTVP() },
"[dbo].[CollectionCipher_UpdateCollections]",
new { CipherId = cipherId, UserId = userId, CollectionIds = collectionIds.ToGuidIdArrayTVP() },
commandType: CommandType.StoredProcedure);
}
}
public async Task UpdateSubvaultsForAdminAsync(Guid cipherId, Guid organizationId, IEnumerable<Guid> subvaultIds)
public async Task UpdateCollectionsForAdminAsync(Guid cipherId, Guid organizationId, IEnumerable<Guid> collectionIds)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.ExecuteAsync(
"[dbo].[SubvaultCipher_UpdateSubvaultsAdmin]",
new { CipherId = cipherId, OrganizationId = organizationId, SubvaultIds = subvaultIds.ToGuidIdArrayTVP() },
"[dbo].[CollectionCipher_UpdateCollectionsAdmin]",
new { CipherId = cipherId, OrganizationId = organizationId, CollectionIds = collectionIds.ToGuidIdArrayTVP() },
commandType: CommandType.StoredProcedure);
}
}

View File

@ -9,13 +9,13 @@ using System.Linq;
namespace Bit.Core.Repositories.SqlServer
{
public class SubvaultRepository : Repository<Subvault, Guid>, ISubvaultRepository
public class CollectionRepository : Repository<Collection, Guid>, ICollectionRepository
{
public SubvaultRepository(GlobalSettings globalSettings)
public CollectionRepository(GlobalSettings globalSettings)
: this(globalSettings.SqlServer.ConnectionString)
{ }
public SubvaultRepository(string connectionString)
public CollectionRepository(string connectionString)
: base(connectionString)
{ }
@ -24,7 +24,7 @@ namespace Bit.Core.Repositories.SqlServer
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.ExecuteScalarAsync<int>(
"[dbo].[Subvault_ReadCountByOrganizationId]",
"[dbo].[Collection_ReadCountByOrganizationId]",
new { OrganizationId = organizationId },
commandType: CommandType.StoredProcedure);
@ -32,11 +32,11 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId)
public async Task<ICollection<Collection>> GetManyByOrganizationIdAsync(Guid organizationId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<Subvault>(
var results = await connection.QueryAsync<Collection>(
$"[{Schema}].[{Table}_ReadByOrganizationId]",
new { OrganizationId = organizationId },
commandType: CommandType.StoredProcedure);
@ -45,11 +45,11 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<Subvault>> GetManyByUserIdAsync(Guid userId)
public async Task<ICollection<Collection>> GetManyByUserIdAsync(Guid userId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<Subvault>(
var results = await connection.QueryAsync<Collection>(
$"[{Schema}].[{Table}_ReadByUserId]",
new { UserId = userId },
commandType: CommandType.StoredProcedure);

View File

@ -10,21 +10,21 @@ using Bit.Core.Models.Data;
namespace Bit.Core.Repositories.SqlServer
{
public class SubvaultUserRepository : Repository<SubvaultUser, Guid>, ISubvaultUserRepository
public class CollectionUserRepository : Repository<CollectionUser, Guid>, ICollectionUserRepository
{
public SubvaultUserRepository(GlobalSettings globalSettings)
public CollectionUserRepository(GlobalSettings globalSettings)
: this(globalSettings.SqlServer.ConnectionString)
{ }
public SubvaultUserRepository(string connectionString)
public CollectionUserRepository(string connectionString)
: base(connectionString)
{ }
public async Task<ICollection<SubvaultUser>> GetManyByOrganizationUserIdAsync(Guid orgUserId)
public async Task<ICollection<CollectionUser>> GetManyByOrganizationUserIdAsync(Guid orgUserId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultUser>(
var results = await connection.QueryAsync<CollectionUser>(
$"[{Schema}].[{Table}_ReadByOrganizationUserId]",
new { OrganizationUserId = orgUserId },
commandType: CommandType.StoredProcedure);
@ -33,12 +33,12 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<SubvaultUserSubvaultDetails>> GetManyDetailsByUserIdAsync(Guid userId)
public async Task<ICollection<CollectionUserCollectionDetails>> GetManyDetailsByUserIdAsync(Guid userId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultUserSubvaultDetails>(
$"[{Schema}].[SubvaultUserSubvaultDetails_ReadByUserId]",
var results = await connection.QueryAsync<CollectionUserCollectionDetails>(
$"[{Schema}].[CollectionUserCollectionDetails_ReadByUserId]",
new { UserId = userId },
commandType: CommandType.StoredProcedure);
@ -46,13 +46,13 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<SubvaultUserUserDetails>> GetManyDetailsBySubvaultIdAsync(Guid subvaultId)
public async Task<ICollection<CollectionUserUserDetails>> GetManyDetailsByCollectionIdAsync(Guid collectionId)
{
using(var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<SubvaultUserUserDetails>(
$"[{Schema}].[SubvaultUserUserDetails_ReadBySubvaultId]",
new { SubvaultId = subvaultId },
var results = await connection.QueryAsync<CollectionUserUserDetails>(
$"[{Schema}].[CollectionUserUserDetails_ReadByCollectionId]",
new { CollectionId = collectionId },
commandType: CommandType.StoredProcedure);
return results.ToList();
@ -64,7 +64,7 @@ namespace Bit.Core.Repositories.SqlServer
using(var connection = new SqlConnection(ConnectionString))
{
var result = await connection.QueryFirstOrDefaultAsync<bool>(
$"[{Schema}].[SubvaultUser_ReadCanEditByCipherIdUserId]",
$"[{Schema}].[CollectionUser_ReadCanEditByCipherIdUserId]",
new { UserId = userId, CipherId = cipherId },
commandType: CommandType.StoredProcedure);

View File

@ -15,10 +15,10 @@ namespace Bit.Core
services.AddSingleton<IGrantRepository, SqlServerRepos.GrantRepository>();
services.AddSingleton<IOrganizationRepository, SqlServerRepos.OrganizationRepository>();
services.AddSingleton<IOrganizationUserRepository, SqlServerRepos.OrganizationUserRepository>();
services.AddSingleton<ISubvaultRepository, SqlServerRepos.SubvaultRepository>();
services.AddSingleton<ISubvaultUserRepository, SqlServerRepos.SubvaultUserRepository>();
services.AddSingleton<ICollectionRepository, SqlServerRepos.CollectionRepository>();
services.AddSingleton<ICollectionUserRepository, SqlServerRepos.CollectionUserRepository>();
services.AddSingleton<IFolderRepository, SqlServerRepos.FolderRepository>();
services.AddSingleton<ISubvaultCipherRepository, SqlServerRepos.SubvaultCipherRepository>();
services.AddSingleton<ICollectionCipherRepository, SqlServerRepos.CollectionCipherRepository>();
}
public static void AddBaseServices(this IServiceCollection services)
@ -27,7 +27,7 @@ namespace Bit.Core
services.AddScoped<IUserService, UserService>();
services.AddScoped<IDeviceService, DeviceService>();
services.AddScoped<IOrganizationService, OrganizationService>();
services.AddScoped<ISubvaultService, SubvaultService>();
services.AddScoped<ICollectionService, CollectionService>();
}
public static void AddDefaultServices(this IServiceCollection services)

View File

@ -12,8 +12,8 @@ namespace Bit.Core.Services
Task DeleteAsync(Cipher cipher, Guid deletingUserId, bool orgAdmin = false);
Task SaveFolderAsync(Folder folder);
Task DeleteFolderAsync(Folder folder);
Task ShareAsync(Cipher cipher, Guid organizationId, IEnumerable<Guid> subvaultIds, Guid userId);
Task SaveSubvaultsAsync(Cipher cipher, IEnumerable<Guid> subvaultIds, Guid savingUserId, bool orgAdmin);
Task ShareAsync(Cipher cipher, Guid organizationId, IEnumerable<Guid> collectionIds, Guid userId);
Task SaveCollectionsAsync(Cipher cipher, IEnumerable<Guid> collectionIds, Guid savingUserId, bool orgAdmin);
Task ImportCiphersAsync(List<Folder> folders, List<CipherDetails> ciphers,
IEnumerable<KeyValuePair<int, int>> folderRelationships);
}

View File

@ -21,11 +21,11 @@ namespace Bit.Core.Services
Task EnableAsync(Guid organizationId);
Task UpdateAsync(Organization organization, bool updateBilling = false);
Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
Enums.OrganizationUserType type, bool accessAllSubvaults, IEnumerable<SubvaultUser> subvaults);
Enums.OrganizationUserType type, bool accessAllCollections, IEnumerable<CollectionUser> collections);
Task ResendInviteAsync(Guid organizationId, Guid invitingUserId, Guid organizationUserId);
Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token);
Task<OrganizationUser> ConfirmUserAsync(Guid organizationId, Guid organizationUserId, string key, Guid confirmingUserId);
Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<SubvaultUser> subvaults);
Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<CollectionUser> collections);
Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId);
Task DeleteUserAsync(Guid organizationId, Guid userId);
}

View File

@ -3,8 +3,8 @@ using Bit.Core.Models.Table;
namespace Bit.Core.Services
{
public interface ISubvaultService
public interface ICollectionService
{
Task SaveAsync(Subvault subvault);
Task SaveAsync(Collection collection);
}
}

View File

@ -16,8 +16,8 @@ namespace Bit.Core.Services
private readonly IUserRepository _userRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ISubvaultUserRepository _subvaultUserRepository;
private readonly ISubvaultCipherRepository _subvaultCipherRepository;
private readonly ICollectionUserRepository _collectionUserRepository;
private readonly ICollectionCipherRepository _collectionCipherRepository;
private readonly IPushService _pushService;
public CipherService(
@ -26,8 +26,8 @@ namespace Bit.Core.Services
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
ISubvaultUserRepository subvaultUserRepository,
ISubvaultCipherRepository subvaultCipherRepository,
ICollectionUserRepository collectionUserRepository,
ICollectionCipherRepository collectionCipherRepository,
IPushService pushService)
{
_cipherRepository = cipherRepository;
@ -35,8 +35,8 @@ namespace Bit.Core.Services
_userRepository = userRepository;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_subvaultUserRepository = subvaultUserRepository;
_subvaultCipherRepository = subvaultCipherRepository;
_collectionUserRepository = collectionUserRepository;
_collectionCipherRepository = collectionCipherRepository;
_pushService = pushService;
}
@ -105,7 +105,7 @@ namespace Bit.Core.Services
await _pushService.PushSyncFolderDeleteAsync(folder);
}
public async Task ShareAsync(Cipher cipher, Guid organizationId, IEnumerable<Guid> subvaultIds, Guid sharingUserId)
public async Task ShareAsync(Cipher cipher, Guid organizationId, IEnumerable<Guid> collectionIds, Guid sharingUserId)
{
if(cipher.Id == default(Guid))
{
@ -122,17 +122,17 @@ namespace Bit.Core.Services
throw new NotFoundException();
}
// Sproc will not save this UserId on the cipher. It is used limit scope of the subvaultIds.
// Sproc will not save this UserId on the cipher. It is used limit scope of the collectionIds.
cipher.UserId = sharingUserId;
cipher.OrganizationId = organizationId;
cipher.RevisionDate = DateTime.UtcNow;
await _cipherRepository.ReplaceAsync(cipher, subvaultIds);
await _cipherRepository.ReplaceAsync(cipher, collectionIds);
// push
await _pushService.PushSyncCipherUpdateAsync(cipher);
}
public async Task SaveSubvaultsAsync(Cipher cipher, IEnumerable<Guid> subvaultIds, Guid savingUserId, bool orgAdmin)
public async Task SaveCollectionsAsync(Cipher cipher, IEnumerable<Guid> collectionIds, Guid savingUserId, bool orgAdmin)
{
if(cipher.Id == default(Guid))
{
@ -144,15 +144,15 @@ namespace Bit.Core.Services
throw new BadRequestException("Cipher must belong to an organization.");
}
// The sprocs will validate that all subvaults belong to this org/user and that they have proper write permissions.
// The sprocs will validate that all collections belong to this org/user and that they have proper write permissions.
if(orgAdmin)
{
await _subvaultCipherRepository.UpdateSubvaultsForAdminAsync(cipher.Id, cipher.OrganizationId.Value,
subvaultIds);
await _collectionCipherRepository.UpdateCollectionsForAdminAsync(cipher.Id, cipher.OrganizationId.Value,
collectionIds);
}
else
{
await _subvaultCipherRepository.UpdateSubvaultsAsync(cipher.Id, savingUserId, subvaultIds);
await _collectionCipherRepository.UpdateCollectionsAsync(cipher.Id, savingUserId, collectionIds);
}
// push
@ -213,7 +213,7 @@ namespace Bit.Core.Services
return true;
}
return await _subvaultUserRepository.GetCanEditByUserIdCipherIdAsync(userId, cipher.Id);
return await _collectionUserRepository.GetCanEditByUserIdCipherIdAsync(userId, cipher.Id);
}
}
}

View File

@ -18,8 +18,8 @@ namespace Bit.Core.Services
{
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ISubvaultRepository _subvaultRepository;
private readonly ISubvaultUserRepository _subvaultUserRepository;
private readonly ICollectionRepository _collectionRepository;
private readonly ICollectionUserRepository _collectionUserRepository;
private readonly IUserRepository _userRepository;
private readonly IDataProtector _dataProtector;
private readonly IMailService _mailService;
@ -28,8 +28,8 @@ namespace Bit.Core.Services
public OrganizationService(
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
ISubvaultRepository subvaultRepository,
ISubvaultUserRepository subvaultUserRepository,
ICollectionRepository collectionRepository,
ICollectionUserRepository collectionUserRepository,
IUserRepository userRepository,
IDataProtectionProvider dataProtectionProvider,
IMailService mailService,
@ -37,8 +37,8 @@ namespace Bit.Core.Services
{
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_subvaultRepository = subvaultRepository;
_subvaultUserRepository = subvaultUserRepository;
_collectionRepository = collectionRepository;
_collectionUserRepository = collectionUserRepository;
_userRepository = userRepository;
_dataProtector = dataProtectionProvider.CreateProtector("OrganizationServiceDataProtector");
_mailService = mailService;
@ -269,15 +269,15 @@ namespace Bit.Core.Services
}
}
if(newPlan.MaxSubvaults.HasValue &&
(!organization.MaxSubvaults.HasValue || organization.MaxSubvaults.Value > newPlan.MaxSubvaults.Value))
if(newPlan.MaxCollections.HasValue &&
(!organization.MaxCollections.HasValue || organization.MaxCollections.Value > newPlan.MaxCollections.Value))
{
var subvaultCount = await _subvaultRepository.GetCountByOrganizationIdAsync(organization.Id);
if(subvaultCount > newPlan.MaxSubvaults.Value)
var collectionCount = await _collectionRepository.GetCountByOrganizationIdAsync(organization.Id);
if(collectionCount > newPlan.MaxCollections.Value)
{
throw new BadRequestException($"Your organization currently has {subvaultCount} subvaults. " +
$"Your new plan allows for a maximum of ({newPlan.MaxSubvaults.Value}) subvaults. " +
"Remove some subvaults.");
throw new BadRequestException($"Your organization currently has {collectionCount} collections. " +
$"Your new plan allows for a maximum of ({newPlan.MaxCollections.Value}) collections. " +
"Remove some collections.");
}
}
@ -551,7 +551,7 @@ namespace Bit.Core.Services
BusinessName = signup.BusinessName,
PlanType = plan.Type,
Seats = (short)(plan.BaseSeats + signup.AdditionalSeats),
MaxSubvaults = plan.MaxSubvaults,
MaxCollections = plan.MaxCollections,
Plan = plan.Name,
StripeCustomerId = customer?.Id,
StripeSubscriptionId = subscription?.Id,
@ -570,7 +570,7 @@ namespace Bit.Core.Services
Key = signup.OwnerKey,
Type = OrganizationUserType.Owner,
Status = OrganizationUserStatusType.Confirmed,
AccessAllSubvaults = true,
AccessAllCollections = true,
CreationDate = DateTime.UtcNow,
RevisionDate = DateTime.UtcNow
};
@ -672,7 +672,7 @@ namespace Bit.Core.Services
}
public async Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
OrganizationUserType type, bool accessAllSubvaults, IEnumerable<SubvaultUser> subvaults)
OrganizationUserType type, bool accessAllCollections, IEnumerable<CollectionUser> collections)
{
var organization = await _organizationRepository.GetByIdAsync(organizationId);
if(organization == null)
@ -705,15 +705,15 @@ namespace Bit.Core.Services
Key = null,
Type = type,
Status = OrganizationUserStatusType.Invited,
AccessAllSubvaults = accessAllSubvaults,
AccessAllCollections = accessAllCollections,
CreationDate = DateTime.UtcNow,
RevisionDate = DateTime.UtcNow
};
await _organizationUserRepository.CreateAsync(orgUser);
if(!orgUser.AccessAllSubvaults && subvaults.Any())
if(!orgUser.AccessAllCollections && collections.Any())
{
await SaveUserSubvaultsAsync(orgUser, subvaults, true);
await SaveUserCollectionsAsync(orgUser, collections, true);
}
await SendInviteAsync(orgUser);
@ -820,7 +820,7 @@ namespace Bit.Core.Services
return orgUser;
}
public async Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<SubvaultUser> subvaults)
public async Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<CollectionUser> collections)
{
if(user.Id.Equals(default(Guid)))
{
@ -835,12 +835,12 @@ namespace Bit.Core.Services
await _organizationUserRepository.ReplaceAsync(user);
if(user.AccessAllSubvaults)
if(user.AccessAllCollections)
{
// We don't need any subvaults if we're flagged to have all access.
subvaults = new List<SubvaultUser>();
// We don't need any collections if we're flagged to have all access.
collections = new List<CollectionUser>();
}
await SaveUserSubvaultsAsync(user, subvaults, false);
await SaveUserCollectionsAsync(user, collections, false);
}
public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId)
@ -889,38 +889,38 @@ namespace Bit.Core.Services
return owners.Where(o => o.Status == Enums.OrganizationUserStatusType.Confirmed);
}
private async Task SaveUserSubvaultsAsync(OrganizationUser user, IEnumerable<SubvaultUser> subvaults, bool newUser)
private async Task SaveUserCollectionsAsync(OrganizationUser user, IEnumerable<CollectionUser> collections, bool newUser)
{
if(subvaults == null)
if(collections == null)
{
subvaults = new List<SubvaultUser>();
collections = new List<CollectionUser>();
}
var orgSubvaults = await _subvaultRepository.GetManyByOrganizationIdAsync(user.OrganizationId);
var currentUserSubvaults = newUser ? null : await _subvaultUserRepository.GetManyByOrganizationUserIdAsync(user.Id);
var orgCollections = await _collectionRepository.GetManyByOrganizationIdAsync(user.OrganizationId);
var currentUserCollections = newUser ? null : await _collectionUserRepository.GetManyByOrganizationUserIdAsync(user.Id);
// Let's make sure all these belong to this user and organization.
var filteredSubvaults = subvaults.Where(s => orgSubvaults.Any(os => os.Id == s.SubvaultId));
foreach(var subvault in filteredSubvaults)
var filteredCollections = collections.Where(s => orgCollections.Any(os => os.Id == s.CollectionId));
foreach(var collection in filteredCollections)
{
var existingSubvaultUser = currentUserSubvaults?.FirstOrDefault(cs => cs.SubvaultId == subvault.SubvaultId);
if(existingSubvaultUser != null)
var existingCollectionUser = currentUserCollections?.FirstOrDefault(cs => cs.CollectionId == collection.CollectionId);
if(existingCollectionUser != null)
{
subvault.Id = existingSubvaultUser.Id;
subvault.CreationDate = existingSubvaultUser.CreationDate;
collection.Id = existingCollectionUser.Id;
collection.CreationDate = existingCollectionUser.CreationDate;
}
subvault.OrganizationUserId = user.Id;
await _subvaultUserRepository.UpsertAsync(subvault);
collection.OrganizationUserId = user.Id;
await _collectionUserRepository.UpsertAsync(collection);
}
if(!newUser)
{
var subvaultsToDelete = currentUserSubvaults.Where(cs =>
!filteredSubvaults.Any(s => s.SubvaultId == cs.SubvaultId));
foreach(var subvault in subvaultsToDelete)
var collectionsToDelete = currentUserCollections.Where(cs =>
!filteredCollections.Any(s => s.CollectionId == cs.CollectionId));
foreach(var collection in collectionsToDelete)
{
await _subvaultUserRepository.DeleteAsync(subvault);
await _collectionUserRepository.DeleteAsync(collection);
}
}
}

View File

@ -6,56 +6,56 @@ using Bit.Core.Repositories;
namespace Bit.Core.Services
{
public class SubvaultService : ISubvaultService
public class CollectionService : ICollectionService
{
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ISubvaultRepository _subvaultRepository;
private readonly ISubvaultUserRepository _subvaultUserRepository;
private readonly ICollectionRepository _collectionRepository;
private readonly ICollectionUserRepository _collectionUserRepository;
private readonly IUserRepository _userRepository;
private readonly IMailService _mailService;
public SubvaultService(
public CollectionService(
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
ISubvaultRepository subvaultRepository,
ISubvaultUserRepository subvaultUserRepository,
ICollectionRepository collectionRepository,
ICollectionUserRepository collectionUserRepository,
IUserRepository userRepository,
IMailService mailService)
{
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_subvaultRepository = subvaultRepository;
_subvaultUserRepository = subvaultUserRepository;
_collectionRepository = collectionRepository;
_collectionUserRepository = collectionUserRepository;
_userRepository = userRepository;
_mailService = mailService;
}
public async Task SaveAsync(Subvault subvault)
public async Task SaveAsync(Collection collection)
{
if(subvault.Id == default(Guid))
if(collection.Id == default(Guid))
{
var org = await _organizationRepository.GetByIdAsync(subvault.OrganizationId);
var org = await _organizationRepository.GetByIdAsync(collection.OrganizationId);
if(org == null)
{
throw new BadRequestException("Org not found");
}
if(org.MaxSubvaults.HasValue)
if(org.MaxCollections.HasValue)
{
var subvaultCount = await _subvaultRepository.GetCountByOrganizationIdAsync(org.Id);
if(org.MaxSubvaults.Value <= subvaultCount)
var collectionCount = await _collectionRepository.GetCountByOrganizationIdAsync(org.Id);
if(org.MaxCollections.Value <= collectionCount)
{
throw new BadRequestException("You have reached the maximum number of subvaults " +
$"({org.MaxSubvaults.Value}) for this organization.");
throw new BadRequestException("You have reached the maximum number of collections " +
$"({org.MaxCollections.Value}) for this organization.");
}
}
await _subvaultRepository.CreateAsync(subvault);
await _collectionRepository.CreateAsync(collection);
}
else
{
await _subvaultRepository.ReplaceAsync(subvault);
await _collectionRepository.ReplaceAsync(collection);
}
}
}

View File

@ -96,7 +96,7 @@ namespace Bit.Core.Utilities
Type = PlanType.Free,
BaseSeats = 2,
CanBuyAdditionalSeats = false,
MaxSubvaults = 2,
MaxCollections = 2,
Name = "Free",
UpgradeSortOrder = -1 // Always the lowest plan, cannot be upgraded to
},