mirror of
https://github.com/bitwarden/server.git
synced 2025-04-22 05:25:10 -05:00
apis for creating ciphers with org & collections
This commit is contained in:
parent
e3f94bb67b
commit
96b492fa07
@ -108,23 +108,42 @@ namespace Bit.Api.Controllers
|
|||||||
{
|
{
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
var cipher = model.ToCipherDetails(userId);
|
var cipher = model.ToCipherDetails(userId);
|
||||||
await _cipherService.SaveDetailsAsync(cipher, userId);
|
if(cipher.OrganizationId.HasValue && !_currentContext.OrganizationUser(cipher.OrganizationId.Value))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _cipherService.SaveDetailsAsync(cipher, userId, null, cipher.OrganizationId.HasValue);
|
||||||
|
var response = new CipherResponseModel(cipher, _globalSettings);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("create")]
|
||||||
|
public async Task<CipherResponseModel> PostCreate([FromBody]CipherCreateRequestModel model)
|
||||||
|
{
|
||||||
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
|
var cipher = model.Cipher.ToCipherDetails(userId);
|
||||||
|
if(cipher.OrganizationId.HasValue && !_currentContext.OrganizationUser(cipher.OrganizationId.Value))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _cipherService.SaveDetailsAsync(cipher, userId, model.CollectionIds, cipher.OrganizationId.HasValue);
|
||||||
var response = new CipherResponseModel(cipher, _globalSettings);
|
var response = new CipherResponseModel(cipher, _globalSettings);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("admin")]
|
[HttpPost("admin")]
|
||||||
public async Task<CipherMiniResponseModel> PostAdmin([FromBody]CipherRequestModel model)
|
public async Task<CipherMiniResponseModel> PostAdmin([FromBody]CipherCreateRequestModel model)
|
||||||
{
|
{
|
||||||
var cipher = model.ToOrganizationCipher();
|
var cipher = model.Cipher.ToOrganizationCipher();
|
||||||
if(!_currentContext.OrganizationAdmin(cipher.OrganizationId.Value))
|
if(!_currentContext.OrganizationAdmin(cipher.OrganizationId.Value))
|
||||||
{
|
{
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
await _cipherService.SaveAsync(cipher, userId, true);
|
await _cipherService.SaveAsync(cipher, userId, model.CollectionIds, true);
|
||||||
|
|
||||||
var response = new CipherMiniResponseModel(cipher, _globalSettings, false);
|
var response = new CipherMiniResponseModel(cipher, _globalSettings, false);
|
||||||
return response;
|
return response;
|
||||||
@ -168,7 +187,7 @@ namespace Bit.Api.Controllers
|
|||||||
|
|
||||||
// object cannot be a descendant of CipherDetails, so let's clone it.
|
// object cannot be a descendant of CipherDetails, so let's clone it.
|
||||||
var cipherClone = CoreHelpers.CloneObject(model.ToCipher(cipher));
|
var cipherClone = CoreHelpers.CloneObject(model.ToCipher(cipher));
|
||||||
await _cipherService.SaveAsync(cipherClone, userId, true);
|
await _cipherService.SaveAsync(cipherClone, userId, null, true);
|
||||||
|
|
||||||
var response = new CipherMiniResponseModel(cipherClone, _globalSettings, cipher.OrganizationUseTotp);
|
var response = new CipherMiniResponseModel(cipherClone, _globalSettings, cipher.OrganizationUseTotp);
|
||||||
return response;
|
return response;
|
||||||
@ -206,7 +225,7 @@ namespace Bit.Api.Controllers
|
|||||||
|
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
var folders = model.Folders.Select(f => f.ToFolder(userId)).ToList();
|
var folders = model.Folders.Select(f => f.ToFolder(userId)).ToList();
|
||||||
var ciphers = model.Ciphers.Select(c => c.ToCipherDetails(userId)).ToList();
|
var ciphers = model.Ciphers.Select(c => c.ToCipherDetails(userId, false)).ToList();
|
||||||
await _cipherService.ImportCiphersAsync(folders, ciphers, model.FolderRelationships);
|
await _cipherService.ImportCiphersAsync(folders, ciphers, model.FolderRelationships);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +36,14 @@ namespace Bit.Core.Models.Api
|
|||||||
public CipherIdentityModel Identity { get; set; }
|
public CipherIdentityModel Identity { get; set; }
|
||||||
public CipherSecureNoteModel SecureNote { 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
|
var cipher = new CipherDetails
|
||||||
{
|
{
|
||||||
Type = Type,
|
Type = Type,
|
||||||
UserId = string.IsNullOrWhiteSpace(OrganizationId) ? (Guid?)userId : null,
|
UserId = !hasOrgId ? (Guid?)userId : null,
|
||||||
OrganizationId = null,
|
OrganizationId = allowOrgIdSet && hasOrgId ? new Guid(OrganizationId) : (Guid?)null,
|
||||||
Edit = true
|
Edit = true
|
||||||
};
|
};
|
||||||
ToCipherDetails(cipher);
|
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
|
public class CipherShareRequestModel : IValidatableObject
|
||||||
{
|
{
|
||||||
[Required]
|
[Required]
|
||||||
|
@ -14,7 +14,9 @@ namespace Bit.Core.Repositories
|
|||||||
Task<bool> GetCanEditByIdAsync(Guid userId, Guid cipherId);
|
Task<bool> GetCanEditByIdAsync(Guid userId, Guid cipherId);
|
||||||
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId, bool withOrganizations = true);
|
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId, bool withOrganizations = true);
|
||||||
Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId);
|
Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||||
|
Task CreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds);
|
||||||
Task CreateAsync(CipherDetails cipher);
|
Task CreateAsync(CipherDetails cipher);
|
||||||
|
Task CreateAsync(CipherDetails cipher, IEnumerable<Guid> collectionIds);
|
||||||
Task ReplaceAsync(CipherDetails cipher);
|
Task ReplaceAsync(CipherDetails cipher);
|
||||||
Task UpsertAsync(CipherDetails cipher);
|
Task UpsertAsync(CipherDetails cipher);
|
||||||
Task<bool> ReplaceAsync(Cipher obj, IEnumerable<Guid> collectionIds);
|
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)
|
public async Task CreateAsync(CipherDetails cipher)
|
||||||
{
|
{
|
||||||
cipher.SetNewId();
|
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)
|
public async Task ReplaceAsync(CipherDetails obj)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
@ -715,6 +745,11 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
return collectionCiphersTable;
|
return collectionCiphersTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CipherDetailsWithCollections : CipherDetails
|
||||||
|
{
|
||||||
|
public DataTable CollectionIds { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class CipherWithCollections : Cipher
|
public class CipherWithCollections : Cipher
|
||||||
{
|
{
|
||||||
public DataTable CollectionIds { get; set; }
|
public DataTable CollectionIds { get; set; }
|
||||||
|
@ -9,8 +9,8 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
public interface ICipherService
|
public interface ICipherService
|
||||||
{
|
{
|
||||||
Task SaveAsync(Cipher cipher, Guid savingUserId, bool orgAdmin = false);
|
Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable<Guid> collectionIds = null, bool skipPermissionCheck = false);
|
||||||
Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId);
|
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,
|
Task CreateAttachmentAsync(Cipher cipher, Stream stream, string fileName, long requestLength, Guid savingUserId,
|
||||||
bool orgAdmin = false);
|
bool orgAdmin = false);
|
||||||
Task CreateAttachmentShareAsync(Cipher cipher, Stream stream, string fileName, long requestLength, string attachmentId,
|
Task CreateAttachmentShareAsync(Cipher cipher, Stream stream, string fileName, long requestLength, string attachmentId,
|
||||||
|
@ -55,16 +55,24 @@ namespace Bit.Core.Services
|
|||||||
_globalSettings = globalSettings;
|
_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.");
|
throw new BadRequestException("You do not have permissions to edit this.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cipher.Id == default(Guid))
|
if(cipher.Id == default(Guid))
|
||||||
|
{
|
||||||
|
if(cipher.OrganizationId.HasValue && collectionIds != null)
|
||||||
|
{
|
||||||
|
await _cipherRepository.CreateAsync(cipher, collectionIds);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
await _cipherRepository.CreateAsync(cipher);
|
await _cipherRepository.CreateAsync(cipher);
|
||||||
|
}
|
||||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||||
|
|
||||||
// push
|
// push
|
||||||
@ -72,6 +80,10 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(collectionIds != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Cannot create cipher with collection ids at the same time.");
|
||||||
|
}
|
||||||
cipher.RevisionDate = DateTime.UtcNow;
|
cipher.RevisionDate = DateTime.UtcNow;
|
||||||
await _cipherRepository.ReplaceAsync(cipher);
|
await _cipherRepository.ReplaceAsync(cipher);
|
||||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||||
@ -81,17 +93,25 @@ 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.");
|
throw new BadRequestException("You do not have permissions to edit this.");
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher.UserId = savingUserId;
|
cipher.UserId = savingUserId;
|
||||||
if(cipher.Id == default(Guid))
|
if(cipher.Id == default(Guid))
|
||||||
|
{
|
||||||
|
if(cipher.OrganizationId.HasValue && collectionIds != null)
|
||||||
|
{
|
||||||
|
await _cipherRepository.CreateAsync(cipher, collectionIds);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
await _cipherRepository.CreateAsync(cipher);
|
await _cipherRepository.CreateAsync(cipher);
|
||||||
|
}
|
||||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||||
|
|
||||||
if(cipher.OrganizationId.HasValue)
|
if(cipher.OrganizationId.HasValue)
|
||||||
@ -105,6 +125,10 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(collectionIds != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Cannot create cipher with collection ids at the same time.");
|
||||||
|
}
|
||||||
cipher.RevisionDate = DateTime.UtcNow;
|
cipher.RevisionDate = DateTime.UtcNow;
|
||||||
await _cipherRepository.ReplaceAsync(cipher);
|
await _cipherRepository.ReplaceAsync(cipher);
|
||||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||||
|
@ -237,5 +237,8 @@
|
|||||||
<Build Include="dbo\Stored Procedures\Collection_CreateWithGroups.sql" />
|
<Build Include="dbo\Stored Procedures\Collection_CreateWithGroups.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\CollectionUser_UpdateUsers.sql" />
|
<Build Include="dbo\Stored Procedures\CollectionUser_UpdateUsers.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\GroupUser_ReadOrganizationUserIdsByGroupId.sql" />
|
<Build Include="dbo\Stored Procedures\GroupUser_ReadOrganizationUserIdsByGroupId.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\Cipher_CreateWithCollections.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\Cipher_UpdateCollections.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\CipherDetails_CreateWithCollections.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -0,0 +1,26 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[CipherDetails_CreateWithCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data NVARCHAR(MAX),
|
||||||
|
@Favorites NVARCHAR(MAX), -- not used
|
||||||
|
@Folders NVARCHAR(MAX), -- not used
|
||||||
|
@Attachments NVARCHAR(MAX), -- not used
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@FolderId UNIQUEIDENTIFIER,
|
||||||
|
@Favorite BIT,
|
||||||
|
@Edit BIT, -- not used
|
||||||
|
@OrganizationUseTotp BIT, -- not used
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
EXEC [dbo].[CipherDetails_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||||
|
@Attachments, @CreationDate, @RevisionDate, @FolderId, @Favorite, @Edit, @OrganizationUseTotp
|
||||||
|
|
||||||
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
|
END
|
@ -0,0 +1,22 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[Cipher_CreateWithCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data NVARCHAR(MAX),
|
||||||
|
@Favorites NVARCHAR(MAX),
|
||||||
|
@Folders NVARCHAR(MAX),
|
||||||
|
@Attachments NVARCHAR(MAX),
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
EXEC [dbo].[Cipher_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||||
|
@Attachments, @CreationDate, @RevisionDate
|
||||||
|
|
||||||
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
|
END
|
67
src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql
Normal file
67
src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[Cipher_UpdateCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
IF @OrganizationId IS NULL OR (SELECT COUNT(1) FROM @CollectionIds) < 1
|
||||||
|
BEGIN
|
||||||
|
RETURN(-1)
|
||||||
|
END
|
||||||
|
|
||||||
|
CREATE TABLE #AvailableCollections (
|
||||||
|
[Id] UNIQUEIDENTIFIER
|
||||||
|
)
|
||||||
|
|
||||||
|
INSERT INTO #AvailableCollections
|
||||||
|
SELECT
|
||||||
|
C.[Id]
|
||||||
|
FROM
|
||||||
|
[dbo].[Collection] C
|
||||||
|
INNER JOIN
|
||||||
|
[Organization] O ON O.[Id] = C.[OrganizationId]
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[Group] G ON G.[Id] = GU.[GroupId]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId]
|
||||||
|
WHERE
|
||||||
|
O.[Id] = @OrganizationId
|
||||||
|
AND O.[Enabled] = 1
|
||||||
|
AND OU.[Status] = 2 -- Confirmed
|
||||||
|
AND (
|
||||||
|
OU.[AccessAll] = 1
|
||||||
|
OR CU.[ReadOnly] = 0
|
||||||
|
OR G.[AccessAll] = 1
|
||||||
|
OR CG.[ReadOnly] = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1
|
||||||
|
BEGIN
|
||||||
|
-- No writable collections available to share with in this organization.
|
||||||
|
RETURN(-1)
|
||||||
|
END
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[CollectionCipher]
|
||||||
|
(
|
||||||
|
[CollectionId],
|
||||||
|
[CipherId]
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
[Id],
|
||||||
|
@Id
|
||||||
|
FROM
|
||||||
|
@CollectionIds
|
||||||
|
WHERE
|
||||||
|
[Id] IN (SELECT [Id] FROM #AvailableCollections)
|
||||||
|
|
||||||
|
RETURN(0)
|
||||||
|
END
|
@ -14,41 +14,14 @@ AS
|
|||||||
BEGIN
|
BEGIN
|
||||||
SET NOCOUNT ON
|
SET NOCOUNT ON
|
||||||
|
|
||||||
CREATE TABLE #AvailableCollections (
|
BEGIN TRANSACTION Cipher_UpdateWithCollections
|
||||||
[Id] UNIQUEIDENTIFIER
|
|
||||||
)
|
|
||||||
|
|
||||||
INSERT INTO #AvailableCollections
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
SELECT
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
C.[Id]
|
|
||||||
FROM
|
|
||||||
[dbo].[Collection] C
|
|
||||||
INNER JOIN
|
|
||||||
[Organization] O ON O.[Id] = C.[OrganizationId]
|
|
||||||
INNER JOIN
|
|
||||||
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId
|
|
||||||
LEFT JOIN
|
|
||||||
[dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id]
|
|
||||||
LEFT JOIN
|
|
||||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id]
|
|
||||||
LEFT JOIN
|
|
||||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId]
|
|
||||||
LEFT JOIN
|
|
||||||
[dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId]
|
|
||||||
WHERE
|
|
||||||
O.[Id] = @OrganizationId
|
|
||||||
AND O.[Enabled] = 1
|
|
||||||
AND OU.[Status] = 2 -- Confirmed
|
|
||||||
AND (
|
|
||||||
OU.[AccessAll] = 1
|
|
||||||
OR CU.[ReadOnly] = 0
|
|
||||||
OR G.[AccessAll] = 1
|
|
||||||
OR CG.[ReadOnly] = 0
|
|
||||||
)
|
|
||||||
|
|
||||||
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1
|
IF @UpdateCollectionsSuccess < 0
|
||||||
BEGIN
|
BEGIN
|
||||||
-- No writable collections available to share with in this organization.
|
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||||
SELECT -1 -- -1 = Failure
|
SELECT -1 -- -1 = Failure
|
||||||
RETURN
|
RETURN
|
||||||
END
|
END
|
||||||
@ -65,18 +38,7 @@ BEGIN
|
|||||||
WHERE
|
WHERE
|
||||||
[Id] = @Id
|
[Id] = @Id
|
||||||
|
|
||||||
INSERT INTO [dbo].[CollectionCipher]
|
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||||
(
|
|
||||||
[CollectionId],
|
|
||||||
[CipherId]
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
[Id],
|
|
||||||
@Id
|
|
||||||
FROM
|
|
||||||
@CollectionIds
|
|
||||||
WHERE
|
|
||||||
[Id] IN (SELECT [Id] FROM #AvailableCollections)
|
|
||||||
|
|
||||||
IF @Attachments IS NOT NULL
|
IF @Attachments IS NOT NULL
|
||||||
BEGIN
|
BEGIN
|
||||||
|
@ -227,3 +227,202 @@ BEGIN
|
|||||||
[GroupId] = @GroupId
|
[GroupId] = @GroupId
|
||||||
END
|
END
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[Cipher_UpdateCollections]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Cipher_UpdateCollections]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Cipher_UpdateCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
IF @OrganizationId IS NULL OR (SELECT COUNT(1) FROM @CollectionIds) < 1
|
||||||
|
BEGIN
|
||||||
|
RETURN(-1)
|
||||||
|
END
|
||||||
|
|
||||||
|
CREATE TABLE #AvailableCollections (
|
||||||
|
[Id] UNIQUEIDENTIFIER
|
||||||
|
)
|
||||||
|
|
||||||
|
INSERT INTO #AvailableCollections
|
||||||
|
SELECT
|
||||||
|
C.[Id]
|
||||||
|
FROM
|
||||||
|
[dbo].[Collection] C
|
||||||
|
INNER JOIN
|
||||||
|
[Organization] O ON O.[Id] = C.[OrganizationId]
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[Group] G ON G.[Id] = GU.[GroupId]
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId]
|
||||||
|
WHERE
|
||||||
|
O.[Id] = @OrganizationId
|
||||||
|
AND O.[Enabled] = 1
|
||||||
|
AND OU.[Status] = 2 -- Confirmed
|
||||||
|
AND (
|
||||||
|
OU.[AccessAll] = 1
|
||||||
|
OR CU.[ReadOnly] = 0
|
||||||
|
OR G.[AccessAll] = 1
|
||||||
|
OR CG.[ReadOnly] = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1
|
||||||
|
BEGIN
|
||||||
|
-- No writable collections available to share with in this organization.
|
||||||
|
RETURN(-1)
|
||||||
|
END
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[CollectionCipher]
|
||||||
|
(
|
||||||
|
[CollectionId],
|
||||||
|
[CipherId]
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
[Id],
|
||||||
|
@Id
|
||||||
|
FROM
|
||||||
|
@CollectionIds
|
||||||
|
WHERE
|
||||||
|
[Id] IN (SELECT [Id] FROM #AvailableCollections)
|
||||||
|
|
||||||
|
RETURN(0)
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[CipherDetails_CreateWithCollections]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[CipherDetails_CreateWithCollections]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[CipherDetails_CreateWithCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data NVARCHAR(MAX),
|
||||||
|
@Favorites NVARCHAR(MAX), -- not used
|
||||||
|
@Folders NVARCHAR(MAX), -- not used
|
||||||
|
@Attachments NVARCHAR(MAX), -- not used
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@FolderId UNIQUEIDENTIFIER,
|
||||||
|
@Favorite BIT,
|
||||||
|
@Edit BIT, -- not used
|
||||||
|
@OrganizationUseTotp BIT, -- not used
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
EXEC [dbo].[CipherDetails_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||||
|
@Attachments, @CreationDate, @RevisionDate, @FolderId, @Favorite, @Edit, @OrganizationUseTotp
|
||||||
|
|
||||||
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[Cipher_CreateWithCollections]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Cipher_CreateWithCollections]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Cipher_CreateWithCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data NVARCHAR(MAX),
|
||||||
|
@Favorites NVARCHAR(MAX),
|
||||||
|
@Folders NVARCHAR(MAX),
|
||||||
|
@Attachments NVARCHAR(MAX),
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
EXEC [dbo].[Cipher_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||||
|
@Attachments, @CreationDate, @RevisionDate
|
||||||
|
|
||||||
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[Cipher_UpdateWithCollections]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Cipher_UpdateWithCollections]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Cipher_UpdateWithCollections]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@UserId UNIQUEIDENTIFIER,
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER,
|
||||||
|
@Type TINYINT,
|
||||||
|
@Data NVARCHAR(MAX),
|
||||||
|
@Favorites NVARCHAR(MAX),
|
||||||
|
@Folders NVARCHAR(MAX),
|
||||||
|
@Attachments NVARCHAR(MAX),
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
BEGIN TRANSACTION Cipher_UpdateWithCollections
|
||||||
|
|
||||||
|
DECLARE @UpdateCollectionsSuccess INT
|
||||||
|
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||||
|
|
||||||
|
IF @UpdateCollectionsSuccess < 0
|
||||||
|
BEGIN
|
||||||
|
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||||
|
SELECT -1 -- -1 = Failure
|
||||||
|
RETURN
|
||||||
|
END
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
[dbo].[Cipher]
|
||||||
|
SET
|
||||||
|
[UserId] = NULL,
|
||||||
|
[OrganizationId] = @OrganizationId,
|
||||||
|
[Data] = @Data,
|
||||||
|
[Attachments] = @Attachments,
|
||||||
|
[RevisionDate] = @RevisionDate
|
||||||
|
-- No need to update CreationDate, Favorites, Folders, or Type since that data will not change
|
||||||
|
WHERE
|
||||||
|
[Id] = @Id
|
||||||
|
|
||||||
|
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||||
|
|
||||||
|
IF @Attachments IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
EXEC [dbo].[Organization_UpdateStorage] @OrganizationId
|
||||||
|
EXEC [dbo].[User_UpdateStorage] @UserId
|
||||||
|
END
|
||||||
|
|
||||||
|
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||||
|
|
||||||
|
SELECT 0 -- 0 = Success
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
Loading…
x
Reference in New Issue
Block a user