16 changed files with 582 additions and 42 deletions
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
using Bit.Core.Enums; |
||||
using Bit.Infrastructure.EntityFramework.Models; |
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Repositories.Queries; |
||||
|
||||
public class CollectionsReadByOrganizationIdUserIdQuery : IQuery<Collection> |
||||
{ |
||||
private readonly Guid? _organizationId; |
||||
private readonly Guid _userId; |
||||
|
||||
public CollectionsReadByOrganizationIdUserIdQuery(Guid? organizationId, Guid userId) |
||||
{ |
||||
_organizationId = organizationId; |
||||
_userId = userId; |
||||
} |
||||
|
||||
public virtual IQueryable<Collection> Run(DatabaseContext dbContext) |
||||
{ |
||||
var query = from c in dbContext.Collections |
||||
join o in dbContext.Organizations on c.OrganizationId equals o.Id |
||||
join ou in dbContext.OrganizationUsers |
||||
on new { OrganizationId = o.Id, UserId = (Guid?)_userId } equals |
||||
new { ou.OrganizationId, ou.UserId } |
||||
join cu in dbContext.CollectionUsers |
||||
on new { CollectionId = c.Id, OrganizationUserId = ou.Id } equals |
||||
new { cu.CollectionId, cu.OrganizationUserId } into cu_g |
||||
from cu in cu_g.DefaultIfEmpty() |
||||
join gu in dbContext.GroupUsers |
||||
on new { CollectionId = (Guid?)cu.CollectionId, OrganizationUserId = ou.Id } equals |
||||
new { CollectionId = (Guid?)null, gu.OrganizationUserId } into gu_g |
||||
from gu in gu_g.DefaultIfEmpty() |
||||
join g in dbContext.Groups on gu.GroupId equals g.Id into g_g |
||||
from g in g_g.DefaultIfEmpty() |
||||
join cg in dbContext.CollectionGroups |
||||
on new { CollectionId = c.Id, gu.GroupId } equals |
||||
new { cg.CollectionId, cg.GroupId } into cg_g |
||||
from cg in cg_g.DefaultIfEmpty() |
||||
where o.Id == _organizationId && o.Enabled && ou.Status == OrganizationUserStatusType.Confirmed |
||||
&& (!cu.ReadOnly || !cg.ReadOnly) |
||||
select c; |
||||
|
||||
return query; |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
CREATE PROCEDURE [dbo].[CollectionCipher_ReadByUserIdCipherId_V2] |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
CC.* |
||||
FROM |
||||
[dbo].[CollectionCipher] CC |
||||
INNER JOIN |
||||
[dbo].[Collection] S ON S.[Id] = CC.[CollectionId] |
||||
INNER JOIN |
||||
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId |
||||
LEFT JOIN |
||||
[dbo].[CollectionUser] CU ON CU.[CollectionId] = S.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
CC.[CipherId] = @CipherId |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[CollectionId] IS NOT NULL |
||||
OR CG.[CollectionId] IS NOT NULL |
||||
) |
||||
END |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
CREATE PROCEDURE [dbo].[CollectionCipher_ReadByUserId_V2] |
||||
@UserId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
CC.* |
||||
FROM |
||||
[dbo].[CollectionCipher] CC |
||||
INNER JOIN |
||||
[dbo].[Collection] S ON S.[Id] = CC.[CollectionId] |
||||
INNER JOIN |
||||
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId |
||||
LEFT JOIN |
||||
[dbo].[CollectionUser] CU ON CU.[CollectionId] = S.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[CollectionId] IS NOT NULL |
||||
OR CG.[CollectionId] IS NOT NULL |
||||
) |
||||
END |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
CREATE PROCEDURE [dbo].[CollectionCipher_UpdateCollectionsForCiphers_V2] |
||||
@CipherIds AS [dbo].[GuidIdArray] READONLY, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
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 CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
O.[Id] = @OrganizationId |
||||
AND O.[Enabled] = 1 |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[ReadOnly] = 0 |
||||
OR CG.[ReadOnly] = 0 |
||||
) |
||||
|
||||
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1 |
||||
BEGIN |
||||
-- No writable collections available to share with in this organization. |
||||
RETURN |
||||
END |
||||
|
||||
INSERT INTO [dbo].[CollectionCipher] |
||||
( |
||||
[CollectionId], |
||||
[CipherId] |
||||
) |
||||
SELECT |
||||
[Collection].[Id], |
||||
[Cipher].[Id] |
||||
FROM |
||||
@CollectionIds [Collection] |
||||
INNER JOIN |
||||
@CipherIds [Cipher] ON 1 = 1 |
||||
WHERE |
||||
[Collection].[Id] IN (SELECT [Id] FROM #AvailableCollections) |
||||
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId |
||||
END |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
CREATE PROCEDURE [dbo].[CollectionCipher_UpdateCollections_V2] |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
DECLARE @OrgId UNIQUEIDENTIFIER = ( |
||||
SELECT TOP 1 |
||||
[OrganizationId] |
||||
FROM |
||||
[dbo].[Cipher] |
||||
WHERE |
||||
[Id] = @CipherId |
||||
) |
||||
|
||||
;WITH [AvailableCollectionsCTE] AS( |
||||
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 CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
O.[Id] = @OrgId |
||||
AND O.[Enabled] = 1 |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[ReadOnly] = 0 |
||||
OR CG.[ReadOnly] = 0 |
||||
) |
||||
), |
||||
[CollectionCiphersCTE] AS( |
||||
SELECT |
||||
[CollectionId], |
||||
[CipherId] |
||||
FROM |
||||
[dbo].[CollectionCipher] |
||||
WHERE |
||||
[CipherId] = @CipherId |
||||
) |
||||
MERGE |
||||
[CollectionCiphersCTE] AS [Target] |
||||
USING |
||||
@CollectionIds AS [Source] |
||||
ON |
||||
[Target].[CollectionId] = [Source].[Id] |
||||
AND [Target].[CipherId] = @CipherId |
||||
WHEN NOT MATCHED BY TARGET |
||||
AND [Source].[Id] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) THEN |
||||
INSERT VALUES |
||||
( |
||||
[Source].[Id], |
||||
@CipherId |
||||
) |
||||
WHEN NOT MATCHED BY SOURCE |
||||
AND [Target].[CipherId] = @CipherId |
||||
AND [Target].[CollectionId] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) THEN |
||||
DELETE |
||||
; |
||||
|
||||
IF @OrgId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId |
||||
END |
||||
END |
||||
@ -0,0 +1,212 @@
@@ -0,0 +1,212 @@
|
||||
-- Flexible Collections: create new CollectionCipher sprocs that don't use AccessAll logic |
||||
|
||||
-- CollectionCipher_ReadByUserId_V2 |
||||
CREATE OR ALTER PROCEDURE [dbo].[CollectionCipher_ReadByUserId_V2] |
||||
@UserId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
CC.* |
||||
FROM |
||||
[dbo].[CollectionCipher] CC |
||||
INNER JOIN |
||||
[dbo].[Collection] S ON S.[Id] = CC.[CollectionId] |
||||
INNER JOIN |
||||
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId |
||||
LEFT JOIN |
||||
[dbo].[CollectionUser] CU ON CU.[CollectionId] = S.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[CollectionId] IS NOT NULL |
||||
OR CG.[CollectionId] IS NOT NULL |
||||
) |
||||
END |
||||
GO |
||||
|
||||
-- CollectionCipher_ReadByUserIdCipherId_V2 |
||||
CREATE OR ALTER PROCEDURE [dbo].[CollectionCipher_ReadByUserIdCipherId_V2] |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
CC.* |
||||
FROM |
||||
[dbo].[CollectionCipher] CC |
||||
INNER JOIN |
||||
[dbo].[Collection] S ON S.[Id] = CC.[CollectionId] |
||||
INNER JOIN |
||||
[dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId |
||||
LEFT JOIN |
||||
[dbo].[CollectionUser] CU ON CU.[CollectionId] = S.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
CC.[CipherId] = @CipherId |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[CollectionId] IS NOT NULL |
||||
OR CG.[CollectionId] IS NOT NULL |
||||
) |
||||
END |
||||
GO |
||||
|
||||
-- CollectionCipher_UpdateCollections_V2 |
||||
CREATE OR ALTER PROCEDURE [dbo].[CollectionCipher_UpdateCollections_V2] |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
DECLARE @OrgId UNIQUEIDENTIFIER = ( |
||||
SELECT TOP 1 |
||||
[OrganizationId] |
||||
FROM |
||||
[dbo].[Cipher] |
||||
WHERE |
||||
[Id] = @CipherId |
||||
) |
||||
|
||||
;WITH [AvailableCollectionsCTE] AS( |
||||
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 CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
O.[Id] = @OrgId |
||||
AND O.[Enabled] = 1 |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[ReadOnly] = 0 |
||||
OR CG.[ReadOnly] = 0 |
||||
) |
||||
), |
||||
[CollectionCiphersCTE] AS( |
||||
SELECT |
||||
[CollectionId], |
||||
[CipherId] |
||||
FROM |
||||
[dbo].[CollectionCipher] |
||||
WHERE |
||||
[CipherId] = @CipherId |
||||
) |
||||
MERGE |
||||
[CollectionCiphersCTE] AS [Target] |
||||
USING |
||||
@CollectionIds AS [Source] |
||||
ON |
||||
[Target].[CollectionId] = [Source].[Id] |
||||
AND [Target].[CipherId] = @CipherId |
||||
WHEN NOT MATCHED BY TARGET |
||||
AND [Source].[Id] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) THEN |
||||
INSERT VALUES |
||||
( |
||||
[Source].[Id], |
||||
@CipherId |
||||
) |
||||
WHEN NOT MATCHED BY SOURCE |
||||
AND [Target].[CipherId] = @CipherId |
||||
AND [Target].[CollectionId] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) THEN |
||||
DELETE |
||||
; |
||||
|
||||
IF @OrgId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId |
||||
END |
||||
END |
||||
GO |
||||
|
||||
-- CollectionCipher_UpdateCollectionsForCiphers_V2 |
||||
CREATE OR ALTER PROCEDURE [dbo].[CollectionCipher_UpdateCollectionsForCiphers_V2] |
||||
@CipherIds AS [dbo].[GuidIdArray] READONLY, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
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 CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
O.[Id] = @OrganizationId |
||||
AND O.[Enabled] = 1 |
||||
AND OU.[Status] = 2 -- Confirmed |
||||
AND ( |
||||
CU.[ReadOnly] = 0 |
||||
OR CG.[ReadOnly] = 0 |
||||
) |
||||
|
||||
IF (SELECT COUNT(1) FROM #AvailableCollections) < 1 |
||||
BEGIN |
||||
-- No writable collections available to share with in this organization. |
||||
RETURN |
||||
END |
||||
|
||||
INSERT INTO [dbo].[CollectionCipher] |
||||
( |
||||
[CollectionId], |
||||
[CipherId] |
||||
) |
||||
SELECT |
||||
[Collection].[Id], |
||||
[Cipher].[Id] |
||||
FROM |
||||
@CollectionIds [Collection] |
||||
INNER JOIN |
||||
@CipherIds [Cipher] ON 1 = 1 |
||||
WHERE |
||||
[Collection].[Id] IN (SELECT [Id] FROM #AvailableCollections) |
||||
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId |
||||
END |
||||
GO |
||||
Loading…
Reference in new issue