mirror of
https://github.com/bitwarden/server.git
synced 2024-11-21 12:05:42 +01:00
[PM-8004] Move Unmanaged collection logic out of component for better reuse (#4108)
* Updated sprocs to return unmanaged collection column, updated reponse to return to return unmanaged * reformatted sproc
This commit is contained in:
parent
b863454a4e
commit
aee180adfc
@ -89,6 +89,7 @@ public class CollectionAccessDetailsResponseModel : CollectionResponseModel
|
||||
ReadOnly = collection.ReadOnly;
|
||||
HidePasswords = collection.HidePasswords;
|
||||
Manage = collection.Manage;
|
||||
Unmanaged = collection.Unmanaged;
|
||||
Groups = collection.Groups?.Select(g => new SelectionReadOnlyResponseModel(g)) ?? Enumerable.Empty<SelectionReadOnlyResponseModel>();
|
||||
Users = collection.Users?.Select(g => new SelectionReadOnlyResponseModel(g)) ?? Enumerable.Empty<SelectionReadOnlyResponseModel>();
|
||||
}
|
||||
@ -104,4 +105,5 @@ public class CollectionAccessDetailsResponseModel : CollectionResponseModel
|
||||
public bool ReadOnly { get; set; }
|
||||
public bool HidePasswords { get; set; }
|
||||
public bool Manage { get; set; }
|
||||
public bool Unmanaged { get; set; }
|
||||
}
|
||||
|
@ -14,4 +14,9 @@ public class CollectionAdminDetails : CollectionDetails
|
||||
/// Flag for whether the user has been explicitly assigned to the collection either directly or through a group.
|
||||
/// </summary>
|
||||
public bool Assigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flag for whether a collection is managed by an active user or group.
|
||||
/// </summary>
|
||||
public bool Unmanaged { get; set; }
|
||||
}
|
||||
|
@ -391,7 +391,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
c.Name,
|
||||
c.CreationDate,
|
||||
c.RevisionDate,
|
||||
c.ExternalId
|
||||
c.ExternalId,
|
||||
c.Unmanaged
|
||||
}).Select(collectionGroup => new CollectionAdminDetails
|
||||
{
|
||||
Id = collectionGroup.Key.Id,
|
||||
@ -404,7 +405,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
HidePasswords =
|
||||
Convert.ToBoolean(collectionGroup.Min(c => Convert.ToInt32(c.HidePasswords))),
|
||||
Manage = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Manage))),
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned)))
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned))),
|
||||
Unmanaged = collectionGroup.Key.Unmanaged
|
||||
}).ToList();
|
||||
}
|
||||
else
|
||||
@ -417,7 +419,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
c.Name,
|
||||
c.CreationDate,
|
||||
c.RevisionDate,
|
||||
c.ExternalId
|
||||
c.ExternalId,
|
||||
c.Unmanaged
|
||||
}
|
||||
into collectionGroup
|
||||
select new CollectionAdminDetails
|
||||
@ -432,7 +435,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
HidePasswords =
|
||||
Convert.ToBoolean(collectionGroup.Min(c => Convert.ToInt32(c.HidePasswords))),
|
||||
Manage = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Manage))),
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned)))
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned))),
|
||||
Unmanaged = collectionGroup.Key.Unmanaged
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
@ -511,7 +515,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
HidePasswords =
|
||||
Convert.ToBoolean(collectionGroup.Min(c => Convert.ToInt32(c.HidePasswords))),
|
||||
Manage = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Manage))),
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned)))
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned))),
|
||||
Unmanaged = collectionGroup.Select(c => c.Unmanaged).FirstOrDefault()
|
||||
}).FirstOrDefault();
|
||||
}
|
||||
else
|
||||
@ -539,7 +544,8 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
HidePasswords =
|
||||
Convert.ToBoolean(collectionGroup.Min(c => Convert.ToInt32(c.HidePasswords))),
|
||||
Manage = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Manage))),
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned)))
|
||||
Assigned = Convert.ToBoolean(collectionGroup.Max(c => Convert.ToInt32(c.Assigned))),
|
||||
Unmanaged = collectionGroup.Select(c => c.Unmanaged).FirstOrDefault()
|
||||
}).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Repositories.Queries;
|
||||
|
||||
@ -46,6 +47,17 @@ public class CollectionAdminDetailsQuery : IQuery<CollectionAdminDetails>
|
||||
from cg in cg_g.DefaultIfEmpty()
|
||||
select new { c, cu, cg };
|
||||
|
||||
// Subqueries to determine if a colection is managed by an active user or group.
|
||||
var activeUserManageRights = from cu in dbContext.CollectionUsers
|
||||
join ou in dbContext.OrganizationUsers
|
||||
on cu.OrganizationUserId equals ou.Id
|
||||
where ou.Status == OrganizationUserStatusType.Confirmed && cu.Manage
|
||||
select cu.CollectionId;
|
||||
|
||||
var activeGroupManageRights = from cg in dbContext.CollectionGroups
|
||||
where cg.Manage
|
||||
select cg.CollectionId;
|
||||
|
||||
if (_organizationId.HasValue)
|
||||
{
|
||||
baseCollectionQuery = baseCollectionQuery.Where(x => x.c.OrganizationId == _organizationId);
|
||||
@ -71,6 +83,7 @@ public class CollectionAdminDetailsQuery : IQuery<CollectionAdminDetails>
|
||||
HidePasswords = (bool?)x.cu.HidePasswords ?? (bool?)x.cg.HidePasswords ?? false,
|
||||
Manage = (bool?)x.cu.Manage ?? (bool?)x.cg.Manage ?? false,
|
||||
Assigned = x.cu != null || x.cg != null,
|
||||
Unmanaged = !activeUserManageRights.Contains(x.c.Id) && !activeGroupManageRights.Contains(x.c.Id),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,29 @@ BEGIN
|
||||
CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Assigned]
|
||||
END) AS [Assigned],
|
||||
CASE
|
||||
WHEN
|
||||
-- No active user or group has manage rights
|
||||
NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionUser] CU2
|
||||
JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id]
|
||||
WHERE
|
||||
CU2.[CollectionId] = C.[Id] AND
|
||||
OU2.[Status] = 2 AND
|
||||
CU2.[Manage] = 1
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionGroup] CG2
|
||||
WHERE
|
||||
CG2.[CollectionId] = C.[Id] AND
|
||||
CG2.[Manage] = 1
|
||||
)
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS [Unmanaged]
|
||||
FROM
|
||||
[dbo].[CollectionView] C
|
||||
LEFT JOIN
|
||||
|
@ -31,7 +31,29 @@ BEGIN
|
||||
CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Assigned]
|
||||
END) AS [Assigned],
|
||||
CASE
|
||||
WHEN
|
||||
-- No active user or group has manage rights
|
||||
NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionUser] CU2
|
||||
JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id]
|
||||
WHERE
|
||||
CU2.[CollectionId] = C.[Id] AND
|
||||
OU2.[Status] = 2 AND
|
||||
CU2.[Manage] = 1
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionGroup] CG2
|
||||
WHERE
|
||||
CG2.[CollectionId] = C.[Id] AND
|
||||
CG2.[Manage] = 1
|
||||
)
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS [Unmanaged]
|
||||
FROM
|
||||
[dbo].[CollectionView] C
|
||||
LEFT JOIN
|
||||
|
@ -310,6 +310,7 @@ public class CollectionRepositoryTests
|
||||
Assert.True(c1.Manage);
|
||||
Assert.False(c1.ReadOnly);
|
||||
Assert.False(c1.HidePasswords);
|
||||
Assert.False(c1.Unmanaged);
|
||||
}, c2 =>
|
||||
{
|
||||
Assert.NotNull(c2);
|
||||
@ -319,6 +320,7 @@ public class CollectionRepositoryTests
|
||||
Assert.False(c2.Manage);
|
||||
Assert.True(c2.ReadOnly);
|
||||
Assert.False(c2.HidePasswords);
|
||||
Assert.True(c2.Unmanaged);
|
||||
}, c3 =>
|
||||
{
|
||||
Assert.NotNull(c3);
|
||||
@ -328,6 +330,7 @@ public class CollectionRepositoryTests
|
||||
Assert.False(c3.Manage);
|
||||
Assert.False(c3.ReadOnly);
|
||||
Assert.False(c3.HidePasswords);
|
||||
Assert.False(c3.Unmanaged);
|
||||
});
|
||||
}
|
||||
|
||||
@ -436,6 +439,7 @@ public class CollectionRepositoryTests
|
||||
Assert.True(c1.Manage);
|
||||
Assert.False(c1.ReadOnly);
|
||||
Assert.False(c1.HidePasswords);
|
||||
Assert.False(c1.Unmanaged);
|
||||
}, c2 =>
|
||||
{
|
||||
Assert.NotNull(c2);
|
||||
@ -445,6 +449,7 @@ public class CollectionRepositoryTests
|
||||
Assert.False(c2.Manage);
|
||||
Assert.True(c2.ReadOnly);
|
||||
Assert.False(c2.HidePasswords);
|
||||
Assert.True(c2.Unmanaged);
|
||||
}, c3 =>
|
||||
{
|
||||
Assert.NotNull(c3);
|
||||
@ -454,6 +459,7 @@ public class CollectionRepositoryTests
|
||||
Assert.True(c3.Manage); // Group 2 is Manage
|
||||
Assert.False(c3.ReadOnly);
|
||||
Assert.False(c3.HidePasswords);
|
||||
Assert.False(c3.Unmanaged);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,171 @@
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Collection_ReadByOrganizationIdWithPermissions]
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@IncludeAccessRelationships BIT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
C.*,
|
||||
MIN(CASE
|
||||
WHEN
|
||||
COALESCE(CU.[ReadOnly], CG.[ReadOnly], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [ReadOnly],
|
||||
MIN(CASE
|
||||
WHEN
|
||||
COALESCE(CU.[HidePasswords], CG.[HidePasswords], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [HidePasswords],
|
||||
MAX(CASE
|
||||
WHEN
|
||||
COALESCE(CU.[Manage], CG.[Manage], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Manage],
|
||||
MAX(CASE
|
||||
WHEN
|
||||
CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Assigned],
|
||||
CASE
|
||||
WHEN
|
||||
-- No active user or group has manage rights
|
||||
NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionUser] CU2
|
||||
JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id]
|
||||
WHERE
|
||||
CU2.[CollectionId] = C.[Id] AND
|
||||
OU2.[Status] = 2 AND
|
||||
CU2.[Manage] = 1
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionGroup] CG2
|
||||
WHERE
|
||||
CG2.[CollectionId] = C.[Id] AND
|
||||
CG2.[Manage] = 1
|
||||
)
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS [Unmanaged]
|
||||
FROM
|
||||
[dbo].[CollectionView] C
|
||||
LEFT JOIN
|
||||
[dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] 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
|
||||
C.[OrganizationId] = @OrganizationId
|
||||
GROUP BY
|
||||
C.[Id],
|
||||
C.[OrganizationId],
|
||||
C.[Name],
|
||||
C.[CreationDate],
|
||||
C.[RevisionDate],
|
||||
C.[ExternalId]
|
||||
|
||||
IF (@IncludeAccessRelationships = 1)
|
||||
BEGIN
|
||||
EXEC [dbo].[CollectionGroup_ReadByOrganizationId] @OrganizationId
|
||||
EXEC [dbo].[CollectionUser_ReadByOrganizationId] @OrganizationId
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Collection_ReadByIdWithPermissions]
|
||||
@CollectionId UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@IncludeAccessRelationships BIT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
C.*,
|
||||
MIN(CASE
|
||||
WHEN
|
||||
COALESCE(CU.[ReadOnly], CG.[ReadOnly], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [ReadOnly],
|
||||
MIN (CASE
|
||||
WHEN
|
||||
COALESCE(CU.[HidePasswords], CG.[HidePasswords], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [HidePasswords],
|
||||
MAX(CASE
|
||||
WHEN
|
||||
COALESCE(CU.[Manage], CG.[Manage], 0) = 0
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Manage],
|
||||
MAX(CASE
|
||||
WHEN
|
||||
CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END) AS [Assigned],
|
||||
CASE
|
||||
WHEN
|
||||
-- No active user or group has manage rights
|
||||
NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionUser] CU2
|
||||
JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id]
|
||||
WHERE
|
||||
CU2.[CollectionId] = C.[Id] AND
|
||||
OU2.[Status] = 2 AND
|
||||
CU2.[Manage] = 1
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM [dbo].[CollectionGroup] CG2
|
||||
WHERE
|
||||
CG2.[CollectionId] = C.[Id] AND
|
||||
CG2.[Manage] = 1
|
||||
)
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS [Unmanaged]
|
||||
FROM
|
||||
[dbo].[CollectionView] C
|
||||
LEFT JOIN
|
||||
[dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] 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
|
||||
C.[Id] = @CollectionId
|
||||
GROUP BY
|
||||
C.[Id],
|
||||
C.[OrganizationId],
|
||||
C.[Name],
|
||||
C.[CreationDate],
|
||||
C.[RevisionDate],
|
||||
C.[ExternalId]
|
||||
|
||||
IF (@IncludeAccessRelationships = 1)
|
||||
BEGIN
|
||||
EXEC [dbo].[CollectionGroup_ReadByCollectionId] @CollectionId
|
||||
EXEC [dbo].[CollectionUser_ReadByCollectionId] @CollectionId
|
||||
END
|
||||
END
|
||||
GO
|
Loading…
Reference in New Issue
Block a user