mirror of
https://github.com/bitwarden/server.git
synced 2025-06-25 13:18:48 -05:00
PM-20112 adding new sql stored procedure
This commit is contained in:
parent
87eae65637
commit
2dd0c2906a
@ -1,9 +1,9 @@
|
||||
using Bit.Api.Tools.Models;
|
||||
using Bit.Api.Tools.Models.Response;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Tools.Entities;
|
||||
using Bit.Core.Tools.Models.Data;
|
||||
using Bit.Core.Tools.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||
using Bit.Core.Tools.ReportFeatures.Requests;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Bit.Core.Tools.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
|
||||
namespace Bit.Api.Tools.Models.Response;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Bit.Core.Tools.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
|
||||
namespace Bit.Api.Tools.Models.Response;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Bit.Core.Tools.Models.Data;
|
||||
namespace Bit.Core.Dirt.Reports.Models.Data;
|
||||
|
||||
public class MemberAccessDetails
|
||||
{
|
||||
@ -30,13 +30,13 @@ public class MemberAccessCipherDetails
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The details for the member's collection access depending
|
||||
/// on the collections and groups they are assigned to
|
||||
/// The details for the member's collection access depending
|
||||
/// on the collections and groups they are assigned to
|
||||
/// </summary>
|
||||
public IEnumerable<MemberAccessDetails> AccessDetails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A distinct list of the cipher ids associated with
|
||||
/// A distinct list of the cipher ids associated with
|
||||
/// the organization member
|
||||
/// </summary>
|
||||
public IEnumerable<string> CipherIds { get; set; }
|
||||
|
@ -2,19 +2,19 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Data.Organizations;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tools.Models.Data;
|
||||
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||
using Bit.Core.Tools.ReportFeatures.Requests;
|
||||
using Bit.Core.Vault.Models.Data;
|
||||
using Bit.Core.Vault.Queries;
|
||||
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
|
||||
|
||||
namespace Bit.Core.Tools.ReportFeatures;
|
||||
|
||||
@ -26,6 +26,7 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
||||
private readonly IOrganizationCiphersQuery _organizationCiphersQuery;
|
||||
private readonly IApplicationCacheService _applicationCacheService;
|
||||
private readonly ITwoFactorIsEnabledQuery _twoFactorIsEnabledQuery;
|
||||
private readonly IMemberAccessCipherDetailsRepository _memberAccessCipherDetailsRepository;
|
||||
|
||||
public MemberAccessCipherDetailsQuery(
|
||||
IOrganizationUserUserDetailsQuery organizationUserUserDetailsQuery,
|
||||
@ -33,7 +34,8 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationCiphersQuery organizationCiphersQuery,
|
||||
IApplicationCacheService applicationCacheService,
|
||||
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery
|
||||
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery,
|
||||
IMemberAccessCipherDetailsRepository memberAccessCipherDetailsRepository
|
||||
)
|
||||
{
|
||||
_organizationUserUserDetailsQuery = organizationUserUserDetailsQuery;
|
||||
@ -42,32 +44,12 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
||||
_organizationCiphersQuery = organizationCiphersQuery;
|
||||
_applicationCacheService = applicationCacheService;
|
||||
_twoFactorIsEnabledQuery = twoFactorIsEnabledQuery;
|
||||
_memberAccessCipherDetailsRepository = memberAccessCipherDetailsRepository;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetails(MemberAccessCipherDetailsRequest request)
|
||||
{
|
||||
var orgUsers = await _organizationUserUserDetailsQuery.GetOrganizationUserUserDetails(
|
||||
new OrganizationUserUserDetailsQueryRequest
|
||||
{
|
||||
OrganizationId = request.OrganizationId,
|
||||
IncludeCollections = true,
|
||||
IncludeGroups = true
|
||||
});
|
||||
|
||||
var orgGroups = await _groupRepository.GetManyByOrganizationIdAsync(request.OrganizationId);
|
||||
var orgAbility = await _applicationCacheService.GetOrganizationAbilityAsync(request.OrganizationId);
|
||||
var orgCollectionsWithAccess = await _collectionRepository.GetManyByOrganizationIdWithAccessAsync(request.OrganizationId);
|
||||
var orgItems = await _organizationCiphersQuery.GetAllOrganizationCiphers(request.OrganizationId);
|
||||
var organizationUsersTwoFactorEnabled = await _twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(orgUsers);
|
||||
|
||||
var memberAccessCipherDetails = GenerateAccessDataParallelV2(
|
||||
orgGroups,
|
||||
orgCollectionsWithAccess,
|
||||
orgItems,
|
||||
organizationUsersTwoFactorEnabled,
|
||||
orgAbility);
|
||||
|
||||
return memberAccessCipherDetails;
|
||||
return await _memberAccessCipherDetailsRepository.GetMemberAccessCipherDetailsByOrganizationId(request.OrganizationId);
|
||||
}
|
||||
|
||||
private IEnumerable<MemberAccessCipherDetails> GenerateAccessData(
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Bit.Core.Tools.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Tools.ReportFeatures.Requests;
|
||||
|
||||
namespace Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||
|
@ -0,0 +1,8 @@
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.Repositories;
|
||||
|
||||
public interface IMemberAccessCipherDetailsRepository
|
||||
{
|
||||
Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetailsByOrganizationId(Guid organizationId);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Billing.Providers.Repositories;
|
||||
using Bit.Core.Billing.Repositories;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Core.KeyManagement.Repositories;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Platform.Installations;
|
||||
@ -12,6 +13,7 @@ using Bit.Core.Vault.Repositories;
|
||||
using Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Auth.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Billing.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Dirt;
|
||||
using Bit.Infrastructure.Dapper.KeyManagement.Repositories;
|
||||
using Bit.Infrastructure.Dapper.NotificationCenter.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Platform;
|
||||
@ -68,6 +70,7 @@ public static class DapperServiceCollectionExtensions
|
||||
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
||||
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
||||
services.AddSingleton<IMemberAccessCipherDetailsRepository, MemberAccessCipherDetailsRepository>();
|
||||
|
||||
if (selfHosted)
|
||||
{
|
||||
|
@ -0,0 +1,40 @@
|
||||
#nullable enable
|
||||
using System.Data;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Core.Settings;
|
||||
|
||||
using Bit.Infrastructure.Dapper.Repositories;
|
||||
using Dapper;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace Bit.Infrastructure.Dapper.Dirt;
|
||||
|
||||
public class MemberAccessCipherDetailsRepository : BaseRepository, IMemberAccessCipherDetailsRepository
|
||||
{
|
||||
public MemberAccessCipherDetailsRepository(GlobalSettings globalSettings)
|
||||
: this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString)
|
||||
{
|
||||
}
|
||||
|
||||
public MemberAccessCipherDetailsRepository(string connectionString, string readOnlyConnectionString) : base(
|
||||
connectionString, readOnlyConnectionString)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetailsByOrganizationId(Guid organizationId)
|
||||
{
|
||||
await using var connection = new SqlConnection(ConnectionString);
|
||||
|
||||
var result = await connection.QueryAsync<MemberAccessCipherDetails>(
|
||||
"[dbo].[MemberAccessReport_GetMemberAccessCipherDetailsByOrganizationId]",
|
||||
new
|
||||
{
|
||||
OrganizationId = organizationId
|
||||
|
||||
}, commandType: CommandType.StoredProcedure);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using AutoMapper;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Dirt;
|
||||
|
||||
public class MemberAccessCipherDetailsRepository : BaseEntityFrameworkRepository, IMemberAccessCipherDetailsRepository
|
||||
{
|
||||
public MemberAccessCipherDetailsRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base(
|
||||
serviceScopeFactory,
|
||||
mapper)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetailsByOrganizationId(Guid organizationId)
|
||||
{
|
||||
await using var scope = ServiceScopeFactory.CreateAsyncScope();
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
|
||||
var result = await dbContext.Set<MemberAccessCipherDetails>()
|
||||
.FromSqlRaw("EXEC [dbo].[MemberAccessReport_GetMemberAccessCipherDetailsByOrganizationId] @OrganizationId",
|
||||
new SqlParameter("@OrganizationId", organizationId))
|
||||
.ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Billing.Providers.Repositories;
|
||||
using Bit.Core.Billing.Repositories;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.KeyManagement.Repositories;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
@ -13,6 +14,7 @@ using Bit.Core.Vault.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Auth.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Billing.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Dirt;
|
||||
using Bit.Infrastructure.EntityFramework.KeyManagement.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.NotificationCenter.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Platform;
|
||||
@ -105,6 +107,7 @@ public static class EntityFrameworkServiceCollectionExtensions
|
||||
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
||||
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
||||
services.AddSingleton<IMemberAccessCipherDetailsRepository, MemberAccessCipherDetailsRepository>();
|
||||
|
||||
if (selfHosted)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
||||
using Bit.Infrastructure.EntityFramework.Auth.Models;
|
||||
@ -80,6 +81,7 @@ public class DatabaseContext : DbContext
|
||||
public DbSet<NotificationStatus> NotificationStatuses { get; set; }
|
||||
public DbSet<ClientOrganizationMigrationRecord> ClientOrganizationMigrationRecords { get; set; }
|
||||
public DbSet<PasswordHealthReportApplication> PasswordHealthReportApplications { get; set; }
|
||||
public DbSet<MemberAccessCipherDetails> MemberAccessCipherDetails { get; set; }
|
||||
public DbSet<SecurityTask> SecurityTasks { get; set; }
|
||||
public DbSet<OrganizationInstallation> OrganizationInstallations { get; set; }
|
||||
|
||||
|
@ -0,0 +1,64 @@
|
||||
CREATE PROCEDURE dbo.MemberAccessReport_GetMemberAccessCipherDetailsByOrganizationId
|
||||
@OrganizationId UNIQUEIDENTIFIER
|
||||
AS
|
||||
SET NOCOUNT ON;
|
||||
|
||||
IF @OrganizationId IS NULL
|
||||
THROW 50000, 'OrganizationId cannot be null', 1;
|
||||
|
||||
SELECT
|
||||
U.Id AS UserGuid,
|
||||
U.Name AS UserName,
|
||||
U.Email,
|
||||
U.TwoFactorProviders,
|
||||
U.UsesKeyConnector,
|
||||
CC.CollectionId,
|
||||
C.Name AS CollectionName,
|
||||
NULL AS GroupId,
|
||||
NULL AS GroupName,
|
||||
CU.ReadOnly,
|
||||
CU.HidePasswords,
|
||||
CU.Manage,
|
||||
cipher.*
|
||||
FROM dbo.OrganizationUser OU
|
||||
INNER JOIN dbo.[User] U ON U.Id = OU.UserId
|
||||
INNER JOIN dbo.Organization O ON O.Id = OU.OrganizationId
|
||||
AND O.Id = @OrganizationId
|
||||
AND O.Enabled = 1
|
||||
INNER JOIN dbo.CollectionUser CU ON CU.OrganizationUserId = OU.Id
|
||||
INNER JOIN dbo.Collection C ON C.Id = CU.CollectionId
|
||||
INNER JOIN dbo.CollectionCipher CC ON CC.CollectionId = C.Id
|
||||
INNER JOIN dbo.Cipher Cipher ON Cipher.Id = CC.CipherId
|
||||
WHERE OU.Status = 2
|
||||
AND Cipher.DeletedDate IS NULL
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Group-based collection permissions
|
||||
SELECT
|
||||
U.Id AS UserGuid,
|
||||
U.Name AS UserName,
|
||||
U.Email,
|
||||
U.TwoFactorProviders,
|
||||
U.UsesKeyConnector,
|
||||
CC.CollectionId,
|
||||
C.Name AS CollectionName,
|
||||
G.Id AS GroupId,
|
||||
G.Name AS GroupName,
|
||||
CG.ReadOnly,
|
||||
CG.HidePasswords,
|
||||
CG.Manage,
|
||||
Cipher.*
|
||||
FROM dbo.OrganizationUser OU
|
||||
INNER JOIN dbo.[User] U ON U.Id = OU.UserId
|
||||
INNER JOIN dbo.Organization O ON O.Id = OU.OrganizationId
|
||||
AND O.Id = @OrganizationId
|
||||
AND O.Enabled = 1
|
||||
INNER JOIN dbo.GroupUser GU ON GU.OrganizationUserId = OU.Id
|
||||
INNER JOIN dbo.[Group] G ON G.Id = GU.GroupId
|
||||
INNER JOIN dbo.CollectionGroup CG ON CG.GroupId = G.Id
|
||||
INNER JOIN dbo.Collection C ON C.Id = CG.CollectionId
|
||||
INNER JOIN dbo.CollectionCipher CC ON CC.CollectionId = C.Id
|
||||
INNER JOIN dbo.Cipher Cipher ON Cipher.Id = CC.CipherId
|
||||
WHERE OU.Status = 2
|
||||
AND Cipher.DeletedDate IS NULL
|
Loading…
x
Reference in New Issue
Block a user