1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-01 16:12:49 -05:00

[AC-2614] Member Access Report Endpoint (#4599)

* Initial draft of moving the org user controller details method into a query

* Removing comments and addressing pr items

* Adding the org users query to core

* Adding the member access report

* Addressing some pr concerns and refactoring to be more efficient

* Some minor changes to the way properties are spelled

* Setting authorization to organization

* Adding the permissions check for reports and comments

* removing unnecessary usings

* Removing ciphers controller change that was a mistake

* There was a duplication issue in getting collections for users grabbing groups

* Adding comments to the CreateReport method

* Only get the user collections by userId

* Some finaly refactoring

* Adding the no group, no collection, and no perms local strings

* Modifying and adding query test cases

* Removing unnecessary permissions code in query

* Added mapping for id and UsesKeyConnector to MemberAccessReportModel (#4681)

* Moving test cases from controller fully into the query.

---------

Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Co-authored-by: aj-rosado <109146700+aj-rosado@users.noreply.github.com>
This commit is contained in:
Tom
2024-09-04 14:33:33 -04:00
committed by GitHub
parent fdf6d8f9c3
commit af3797c540
12 changed files with 503 additions and 95 deletions

View File

@ -1,4 +1,6 @@
namespace Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Core.Enums;
public enum OrganizationUserType : byte
{
@ -8,3 +10,35 @@ public enum OrganizationUserType : byte
// Manager = 3 has been intentionally permanently deleted
Custom = 4,
}
public static class OrganizationUserTypeExtensions
{
public static OrganizationUserType GetFlexibleCollectionsUserType(this OrganizationUserType type, Permissions permissions)
{
// Downgrade Custom users with no other permissions than 'Edit/Delete Assigned Collections' to User
if (type == OrganizationUserType.Custom && permissions is not null)
{
if ((permissions.EditAssignedCollections || permissions.DeleteAssignedCollections) &&
permissions is
{
AccessEventLogs: false,
AccessImportExport: false,
AccessReports: false,
CreateNewCollections: false,
EditAnyCollection: false,
DeleteAnyCollection: false,
ManageGroups: false,
ManagePolicies: false,
ManageSso: false,
ManageUsers: false,
ManageResetPassword: false,
ManageScim: false
})
{
return OrganizationUserType.User;
}
}
return type;
}
}

View File

@ -0,0 +1,9 @@
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
namespace Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
public interface IOrganizationUserUserDetailsQuery
{
Task<IEnumerable<OrganizationUserUserDetails>> GetOrganizationUserUserDetails(OrganizationUserUserDetailsQueryRequest request);
}

View File

@ -0,0 +1,50 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Repositories;
using Bit.Core.Utilities;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
namespace Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
public class OrganizationUserUserDetailsQuery : IOrganizationUserUserDetailsQuery
{
private readonly IOrganizationUserRepository _organizationUserRepository;
public OrganizationUserUserDetailsQuery(
IOrganizationUserRepository organizationUserRepository
)
{
_organizationUserRepository = organizationUserRepository;
}
/// <summary>
/// Gets the organization user user details for the provided request
/// </summary>
/// <param name="request">Request details for the query</param>
/// <returns>List of OrganizationUserUserDetails</returns>
public async Task<IEnumerable<OrganizationUserUserDetails>> GetOrganizationUserUserDetails(OrganizationUserUserDetailsQueryRequest request)
{
var organizationUsers = await _organizationUserRepository
.GetManyDetailsByOrganizationAsync(request.OrganizationId, request.IncludeGroups, request.IncludeCollections);
return organizationUsers
.Select(o =>
{
var userPermissions = o.GetPermissions();
// Downgrade Custom users with no other permissions than 'Edit/Delete Assigned Collections' to User
o.Type = o.Type.GetFlexibleCollectionsUserType(userPermissions);
if (userPermissions is not null)
{
userPermissions.EditAssignedCollections = false;
userPermissions.DeleteAssignedCollections = false;
}
o.Permissions = CoreHelpers.ClassToJsonData(userPermissions);
return o;
});
}
}

View File

@ -0,0 +1,8 @@
namespace Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
public class OrganizationUserUserDetailsQueryRequest
{
public Guid OrganizationId { get; set; }
public bool IncludeGroups { get; set; } = false;
public bool IncludeCollections { get; set; } = false;
}

View File

@ -26,6 +26,8 @@ using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Tokens;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -136,6 +138,7 @@ public static class OrganizationServiceCollectionExtensions
{
services.AddScoped<ICountNewSmSeatsRequiredQuery, CountNewSmSeatsRequiredQuery>();
services.AddScoped<IAcceptOrgUserCommand, AcceptOrgUserCommand>();
services.AddScoped<IOrganizationUserUserDetailsQuery, OrganizationUserUserDetailsQuery>();
}
// TODO: move to OrganizationSubscriptionServiceCollectionExtensions when OrganizationUser methods are moved out of