mirror of
https://github.com/bitwarden/server.git
synced 2025-06-25 21:28:47 -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;
|
||||||
using Bit.Api.Tools.Models.Response;
|
using Bit.Api.Tools.Models.Response;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Dirt.Reports.Models.Data;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Tools.Entities;
|
using Bit.Core.Tools.Entities;
|
||||||
using Bit.Core.Tools.Models.Data;
|
|
||||||
using Bit.Core.Tools.ReportFeatures.Interfaces;
|
using Bit.Core.Tools.ReportFeatures.Interfaces;
|
||||||
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||||
using Bit.Core.Tools.ReportFeatures.Requests;
|
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;
|
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;
|
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
|
public class MemberAccessDetails
|
||||||
{
|
{
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
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.Entities;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Models.Data.Organizations;
|
using Bit.Core.Models.Data.Organizations;
|
||||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Tools.Models.Data;
|
|
||||||
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||||
using Bit.Core.Tools.ReportFeatures.Requests;
|
using Bit.Core.Tools.ReportFeatures.Requests;
|
||||||
using Bit.Core.Vault.Models.Data;
|
using Bit.Core.Vault.Models.Data;
|
||||||
using Bit.Core.Vault.Queries;
|
using Bit.Core.Vault.Queries;
|
||||||
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||||
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
|
|
||||||
|
|
||||||
namespace Bit.Core.Tools.ReportFeatures;
|
namespace Bit.Core.Tools.ReportFeatures;
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
|||||||
private readonly IOrganizationCiphersQuery _organizationCiphersQuery;
|
private readonly IOrganizationCiphersQuery _organizationCiphersQuery;
|
||||||
private readonly IApplicationCacheService _applicationCacheService;
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
private readonly ITwoFactorIsEnabledQuery _twoFactorIsEnabledQuery;
|
private readonly ITwoFactorIsEnabledQuery _twoFactorIsEnabledQuery;
|
||||||
|
private readonly IMemberAccessCipherDetailsRepository _memberAccessCipherDetailsRepository;
|
||||||
|
|
||||||
public MemberAccessCipherDetailsQuery(
|
public MemberAccessCipherDetailsQuery(
|
||||||
IOrganizationUserUserDetailsQuery organizationUserUserDetailsQuery,
|
IOrganizationUserUserDetailsQuery organizationUserUserDetailsQuery,
|
||||||
@ -33,7 +34,8 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
|||||||
ICollectionRepository collectionRepository,
|
ICollectionRepository collectionRepository,
|
||||||
IOrganizationCiphersQuery organizationCiphersQuery,
|
IOrganizationCiphersQuery organizationCiphersQuery,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery
|
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery,
|
||||||
|
IMemberAccessCipherDetailsRepository memberAccessCipherDetailsRepository
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_organizationUserUserDetailsQuery = organizationUserUserDetailsQuery;
|
_organizationUserUserDetailsQuery = organizationUserUserDetailsQuery;
|
||||||
@ -42,32 +44,12 @@ public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery
|
|||||||
_organizationCiphersQuery = organizationCiphersQuery;
|
_organizationCiphersQuery = organizationCiphersQuery;
|
||||||
_applicationCacheService = applicationCacheService;
|
_applicationCacheService = applicationCacheService;
|
||||||
_twoFactorIsEnabledQuery = twoFactorIsEnabledQuery;
|
_twoFactorIsEnabledQuery = twoFactorIsEnabledQuery;
|
||||||
|
_memberAccessCipherDetailsRepository = memberAccessCipherDetailsRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetails(MemberAccessCipherDetailsRequest request)
|
public async Task<IEnumerable<MemberAccessCipherDetails>> GetMemberAccessCipherDetails(MemberAccessCipherDetailsRequest request)
|
||||||
{
|
{
|
||||||
var orgUsers = await _organizationUserUserDetailsQuery.GetOrganizationUserUserDetails(
|
return await _memberAccessCipherDetailsRepository.GetMemberAccessCipherDetailsByOrganizationId(request.OrganizationId);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<MemberAccessCipherDetails> GenerateAccessData(
|
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;
|
using Bit.Core.Tools.ReportFeatures.Requests;
|
||||||
|
|
||||||
namespace Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces;
|
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.Auth.Repositories;
|
||||||
using Bit.Core.Billing.Providers.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Repositories;
|
||||||
|
using Bit.Core.Dirt.Reports.Repositories;
|
||||||
using Bit.Core.KeyManagement.Repositories;
|
using Bit.Core.KeyManagement.Repositories;
|
||||||
using Bit.Core.NotificationCenter.Repositories;
|
using Bit.Core.NotificationCenter.Repositories;
|
||||||
using Bit.Core.Platform.Installations;
|
using Bit.Core.Platform.Installations;
|
||||||
@ -12,6 +13,7 @@ using Bit.Core.Vault.Repositories;
|
|||||||
using Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
using Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
||||||
using Bit.Infrastructure.Dapper.Auth.Repositories;
|
using Bit.Infrastructure.Dapper.Auth.Repositories;
|
||||||
using Bit.Infrastructure.Dapper.Billing.Repositories;
|
using Bit.Infrastructure.Dapper.Billing.Repositories;
|
||||||
|
using Bit.Infrastructure.Dapper.Dirt;
|
||||||
using Bit.Infrastructure.Dapper.KeyManagement.Repositories;
|
using Bit.Infrastructure.Dapper.KeyManagement.Repositories;
|
||||||
using Bit.Infrastructure.Dapper.NotificationCenter.Repositories;
|
using Bit.Infrastructure.Dapper.NotificationCenter.Repositories;
|
||||||
using Bit.Infrastructure.Dapper.Platform;
|
using Bit.Infrastructure.Dapper.Platform;
|
||||||
@ -68,6 +70,7 @@ public static class DapperServiceCollectionExtensions
|
|||||||
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||||
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
||||||
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
||||||
|
services.AddSingleton<IMemberAccessCipherDetailsRepository, MemberAccessCipherDetailsRepository>();
|
||||||
|
|
||||||
if (selfHosted)
|
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.Auth.Repositories;
|
||||||
using Bit.Core.Billing.Providers.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Repositories;
|
||||||
|
using Bit.Core.Dirt.Reports.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.KeyManagement.Repositories;
|
using Bit.Core.KeyManagement.Repositories;
|
||||||
using Bit.Core.NotificationCenter.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.AdminConsole.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Auth.Repositories;
|
using Bit.Infrastructure.EntityFramework.Auth.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Billing.Repositories;
|
using Bit.Infrastructure.EntityFramework.Billing.Repositories;
|
||||||
|
using Bit.Infrastructure.EntityFramework.Dirt;
|
||||||
using Bit.Infrastructure.EntityFramework.KeyManagement.Repositories;
|
using Bit.Infrastructure.EntityFramework.KeyManagement.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.NotificationCenter.Repositories;
|
using Bit.Infrastructure.EntityFramework.NotificationCenter.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Platform;
|
using Bit.Infrastructure.EntityFramework.Platform;
|
||||||
@ -105,6 +107,7 @@ public static class EntityFrameworkServiceCollectionExtensions
|
|||||||
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||||
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
services.AddSingleton<IUserAsymmetricKeysRepository, UserAsymmetricKeysRepository>();
|
||||||
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
services.AddSingleton<IOrganizationInstallationRepository, OrganizationInstallationRepository>();
|
||||||
|
services.AddSingleton<IMemberAccessCipherDetailsRepository, MemberAccessCipherDetailsRepository>();
|
||||||
|
|
||||||
if (selfHosted)
|
if (selfHosted)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
|
using Bit.Core.Dirt.Reports.Models.Data;
|
||||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models;
|
using Bit.Infrastructure.EntityFramework.AdminConsole.Models;
|
||||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
||||||
using Bit.Infrastructure.EntityFramework.Auth.Models;
|
using Bit.Infrastructure.EntityFramework.Auth.Models;
|
||||||
@ -80,6 +81,7 @@ public class DatabaseContext : DbContext
|
|||||||
public DbSet<NotificationStatus> NotificationStatuses { get; set; }
|
public DbSet<NotificationStatus> NotificationStatuses { get; set; }
|
||||||
public DbSet<ClientOrganizationMigrationRecord> ClientOrganizationMigrationRecords { get; set; }
|
public DbSet<ClientOrganizationMigrationRecord> ClientOrganizationMigrationRecords { get; set; }
|
||||||
public DbSet<PasswordHealthReportApplication> PasswordHealthReportApplications { get; set; }
|
public DbSet<PasswordHealthReportApplication> PasswordHealthReportApplications { get; set; }
|
||||||
|
public DbSet<MemberAccessCipherDetails> MemberAccessCipherDetails { get; set; }
|
||||||
public DbSet<SecurityTask> SecurityTasks { get; set; }
|
public DbSet<SecurityTask> SecurityTasks { get; set; }
|
||||||
public DbSet<OrganizationInstallation> OrganizationInstallations { 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