mirror of
https://github.com/bitwarden/server.git
synced 2025-02-15 01:41:40 +01: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 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);
|
||||
return response;
|
||||
}
|
||||
|
||||
[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))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
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);
|
||||
return response;
|
||||
@ -168,7 +187,7 @@ namespace Bit.Api.Controllers
|
||||
|
||||
// object cannot be a descendant of CipherDetails, so let's clone it.
|
||||
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);
|
||||
return response;
|
||||
@ -206,7 +225,7 @@ namespace Bit.Api.Controllers
|
||||
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -237,5 +237,8 @@
|
||||
<Build Include="dbo\Stored Procedures\Collection_CreateWithGroups.sql" />
|
||||
<Build Include="dbo\Stored Procedures\CollectionUser_UpdateUsers.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>
|
||||
</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
|
||||
SET NOCOUNT ON
|
||||
|
||||
CREATE TABLE #AvailableCollections (
|
||||
[Id] UNIQUEIDENTIFIER
|
||||
)
|
||||
BEGIN TRANSACTION Cipher_UpdateWithCollections
|
||||
|
||||
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
|
||||
)
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
|
||||
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1
|
||||
IF @UpdateCollectionsSuccess < 0
|
||||
BEGIN
|
||||
-- No writable collections available to share with in this organization.
|
||||
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||
SELECT -1 -- -1 = Failure
|
||||
RETURN
|
||||
END
|
||||
@ -65,18 +38,7 @@ BEGIN
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
INSERT INTO [dbo].[CollectionCipher]
|
||||
(
|
||||
[CollectionId],
|
||||
[CipherId]
|
||||
)
|
||||
SELECT
|
||||
[Id],
|
||||
@Id
|
||||
FROM
|
||||
@CollectionIds
|
||||
WHERE
|
||||
[Id] IN (SELECT [Id] FROM #AvailableCollections)
|
||||
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||
|
||||
IF @Attachments IS NOT NULL
|
||||
BEGIN
|
||||
|
@ -227,3 +227,202 @@ BEGIN
|
||||
[GroupId] = @GroupId
|
||||
END
|
||||
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…
Reference in New Issue
Block a user