mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
apis for creating ciphers with org & collections
This commit is contained in:
@ -36,13 +36,14 @@ namespace Bit.Core.Models.Api
|
||||
public CipherIdentityModel Identity { get; set; }
|
||||
public CipherSecureNoteModel SecureNote { get; set; }
|
||||
|
||||
public CipherDetails ToCipherDetails(Guid userId)
|
||||
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
|
||||
{
|
||||
var hasOrgId = !string.IsNullOrWhiteSpace(OrganizationId);
|
||||
var cipher = new CipherDetails
|
||||
{
|
||||
Type = Type,
|
||||
UserId = string.IsNullOrWhiteSpace(OrganizationId) ? (Guid?)userId : null,
|
||||
OrganizationId = null,
|
||||
UserId = !hasOrgId ? (Guid?)userId : null,
|
||||
OrganizationId = allowOrgIdSet && hasOrgId ? new Guid(OrganizationId) : (Guid?)null,
|
||||
Edit = true
|
||||
};
|
||||
ToCipherDetails(cipher);
|
||||
@ -142,6 +143,22 @@ namespace Bit.Core.Models.Api
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherCreateRequestModel : IValidatableObject
|
||||
{
|
||||
public IEnumerable<Guid> CollectionIds { get; set; }
|
||||
[Required]
|
||||
public CipherRequestModel Cipher { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(Cipher.OrganizationId) && (!CollectionIds?.Any() ?? true))
|
||||
{
|
||||
yield return new ValidationResult("You must select at least one collection.",
|
||||
new string[] { nameof(CollectionIds) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherShareRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
|
@ -14,7 +14,9 @@ namespace Bit.Core.Repositories
|
||||
Task<bool> GetCanEditByIdAsync(Guid userId, Guid cipherId);
|
||||
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId, bool withOrganizations = true);
|
||||
Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||
Task CreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds);
|
||||
Task CreateAsync(CipherDetails cipher);
|
||||
Task CreateAsync(CipherDetails cipher, IEnumerable<Guid> collectionIds);
|
||||
Task ReplaceAsync(CipherDetails cipher);
|
||||
Task UpsertAsync(CipherDetails cipher);
|
||||
Task<bool> ReplaceAsync(Cipher obj, IEnumerable<Guid> collectionIds);
|
||||
|
@ -101,6 +101,21 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds)
|
||||
{
|
||||
cipher.SetNewId();
|
||||
var objWithCollections = JsonConvert.DeserializeObject<CipherWithCollections>(
|
||||
JsonConvert.SerializeObject(cipher));
|
||||
objWithCollections.CollectionIds = collectionIds.ToGuidIdArrayTVP();
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.ExecuteAsync(
|
||||
$"[{Schema}].[Cipher_CreateWithCollections]",
|
||||
objWithCollections,
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateAsync(CipherDetails cipher)
|
||||
{
|
||||
cipher.SetNewId();
|
||||
@ -113,6 +128,21 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateAsync(CipherDetails cipher, IEnumerable<Guid> collectionIds)
|
||||
{
|
||||
cipher.SetNewId();
|
||||
var objWithCollections = JsonConvert.DeserializeObject<CipherDetailsWithCollections>(
|
||||
JsonConvert.SerializeObject(cipher));
|
||||
objWithCollections.CollectionIds = collectionIds.ToGuidIdArrayTVP();
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.ExecuteAsync(
|
||||
$"[{Schema}].[CipherDetails_CreateWithCollections]",
|
||||
objWithCollections,
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ReplaceAsync(CipherDetails obj)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
@ -715,6 +745,11 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
return collectionCiphersTable;
|
||||
}
|
||||
|
||||
public class CipherDetailsWithCollections : CipherDetails
|
||||
{
|
||||
public DataTable CollectionIds { get; set; }
|
||||
}
|
||||
|
||||
public class CipherWithCollections : Cipher
|
||||
{
|
||||
public DataTable CollectionIds { get; set; }
|
||||
|
@ -9,8 +9,8 @@ namespace Bit.Core.Services
|
||||
{
|
||||
public interface ICipherService
|
||||
{
|
||||
Task SaveAsync(Cipher cipher, Guid savingUserId, bool orgAdmin = false);
|
||||
Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId);
|
||||
Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable<Guid> collectionIds = null, bool skipPermissionCheck = false);
|
||||
Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId, IEnumerable<Guid> collectionIds = null, bool skipPermissionCheck = false);
|
||||
Task CreateAttachmentAsync(Cipher cipher, Stream stream, string fileName, long requestLength, Guid savingUserId,
|
||||
bool orgAdmin = false);
|
||||
Task CreateAttachmentShareAsync(Cipher cipher, Stream stream, string fileName, long requestLength, string attachmentId,
|
||||
|
@ -55,16 +55,24 @@ namespace Bit.Core.Services
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public async Task SaveAsync(Cipher cipher, Guid savingUserId, bool orgAdmin = false)
|
||||
public async Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable<Guid> collectionIds = null,
|
||||
bool skipPermissionCheck = false)
|
||||
{
|
||||
if(!orgAdmin && !(await UserCanEditAsync(cipher, savingUserId)))
|
||||
if(!skipPermissionCheck && !(await UserCanEditAsync(cipher, savingUserId)))
|
||||
{
|
||||
throw new BadRequestException("You do not have permissions to edit this.");
|
||||
}
|
||||
|
||||
if(cipher.Id == default(Guid))
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
if(cipher.OrganizationId.HasValue && collectionIds != null)
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher, collectionIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
}
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||
|
||||
// push
|
||||
@ -72,6 +80,10 @@ namespace Bit.Core.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
if(collectionIds != null)
|
||||
{
|
||||
throw new ArgumentException("Cannot create cipher with collection ids at the same time.");
|
||||
}
|
||||
cipher.RevisionDate = DateTime.UtcNow;
|
||||
await _cipherRepository.ReplaceAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||
@ -81,9 +93,10 @@ namespace Bit.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId)
|
||||
public async Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId,
|
||||
IEnumerable<Guid> collectionIds = null, bool skipPermissionCheck = false)
|
||||
{
|
||||
if(!(await UserCanEditAsync(cipher, savingUserId)))
|
||||
if(!skipPermissionCheck && !(await UserCanEditAsync(cipher, savingUserId)))
|
||||
{
|
||||
throw new BadRequestException("You do not have permissions to edit this.");
|
||||
}
|
||||
@ -91,7 +104,14 @@ namespace Bit.Core.Services
|
||||
cipher.UserId = savingUserId;
|
||||
if(cipher.Id == default(Guid))
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
if(cipher.OrganizationId.HasValue && collectionIds != null)
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher, collectionIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
}
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||
|
||||
if(cipher.OrganizationId.HasValue)
|
||||
@ -105,6 +125,10 @@ namespace Bit.Core.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
if(collectionIds != null)
|
||||
{
|
||||
throw new ArgumentException("Cannot create cipher with collection ids at the same time.");
|
||||
}
|
||||
cipher.RevisionDate = DateTime.UtcNow;
|
||||
await _cipherRepository.ReplaceAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||
|
Reference in New Issue
Block a user