1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00

All attributes all the time

This commit is contained in:
Thomas Rittson 2025-03-21 13:21:52 +10:00
parent dd67c41ed7
commit dad05fca77
No known key found for this signature in database
GPG Key ID: CDDDA03861C35E27
3 changed files with 40 additions and 30 deletions

View File

@ -146,16 +146,9 @@ public class OrganizationUsersController : Controller
} }
[HttpGet("")] [HttpGet("")]
[RoleRequirement(OrganizationUserType.Owner)] [ManageUsersRequirement]
public async Task<ListResponseModel<OrganizationUserUserDetailsResponseModel>> Get(Guid orgId, bool includeGroups = false, bool includeCollections = false) public async Task<ListResponseModel<OrganizationUserUserDetailsResponseModel>> Get(Guid orgId, bool includeGroups = false, bool includeCollections = false)
{ {
// var authorized = (await _authorizationService.AuthorizeAsync(
// User, new OrganizationScope(orgId), OrganizationUserUserDetailsOperations.ReadAll)).Succeeded;
// if (!authorized)
// {
// throw new NotFoundException();
// }
var organizationUsers = await _organizationUserUserDetailsQuery.GetOrganizationUserUserDetails( var organizationUsers = await _organizationUserUserDetailsQuery.GetOrganizationUserUserDetails(
new OrganizationUserUserDetailsQueryRequest new OrganizationUserUserDetailsQueryRequest
{ {

View File

@ -107,6 +107,6 @@ public static class ServiceCollectionExtensions
services.AddScoped<IAuthorizationHandler, SecurityTaskAuthorizationHandler>(); services.AddScoped<IAuthorizationHandler, SecurityTaskAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, SecurityTaskOrganizationAuthorizationHandler>(); services.AddScoped<IAuthorizationHandler, SecurityTaskOrganizationAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, RoleAuthorizationHandler>(); services.AddScoped<IAuthorizationHandler, AdminConsoleRequirementsHandler>();
} }
} }

View File

@ -1,4 +1,6 @@
using Bit.Core.Context; #nullable enable
using Bit.Core.Context;
using Bit.Core.Enums; using Bit.Core.Enums;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -6,43 +8,58 @@ using Microsoft.AspNetCore.Routing;
namespace Bit.Core.AdminConsole.OrganizationFeatures; namespace Bit.Core.AdminConsole.OrganizationFeatures;
public class RoleRequirementAttribute public abstract class OrganizationRequirementAttribute
: AuthorizeAttribute, IAuthorizationRequirement, IAuthorizationRequirementData : AuthorizeAttribute, IAuthorizationRequirement, IAuthorizationRequirementData
{ {
public OrganizationUserType Role { get; set; } public IEnumerable<IAuthorizationRequirement> GetRequirements() => [this];
public RoleRequirementAttribute(OrganizationUserType type)
{
Role = type;
}
public IEnumerable<IAuthorizationRequirement> GetRequirements()
{
yield return this;
}
} }
public class RoleAuthorizationHandler(ICurrentContext currentContext, IHttpContextAccessor httpContextAccessor) : AuthorizationHandler<RoleRequirementAttribute> public abstract class OrganizationRequirementHandler : AuthorizationHandler<OrganizationRequirementAttribute>
{ {
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirementAttribute requirementAttribute) protected Guid? OrganizationId { get; set; }
protected CurrentContextOrganization? Organization { get; set; }
protected OrganizationRequirementHandler(ICurrentContext currentContext, IHttpContextAccessor httpContextAccessor)
{ {
if (httpContextAccessor.HttpContext is null) if (httpContextAccessor.HttpContext is null)
{ {
return Task.CompletedTask; return;
} }
httpContextAccessor.HttpContext.GetRouteData().Values.TryGetValue("orgId", out var orgIdParam); httpContextAccessor.HttpContext.GetRouteData().Values.TryGetValue("orgId", out var orgIdParam);
if (!Guid.TryParse(orgIdParam?.ToString(), out var orgId)) if (!Guid.TryParse(orgIdParam?.ToString(), out var orgId))
{ {
// No orgId supplied, unable to authorize // No orgId supplied, unable to authorize
return Task.CompletedTask; return;
} }
// This could be an extension method on ClaimsPrincipal OrganizationId = orgId;
var orgClaims = currentContext.GetOrganization(orgId); if (OrganizationId.HasValue)
if (orgClaims?.Type == requirementAttribute.Role)
{ {
context.Succeed(requirementAttribute); Organization = currentContext.GetOrganization(OrganizationId.Value);
}
}
}
public class ManageUsersRequirementAttribute : OrganizationRequirementAttribute;
public class AdminConsoleRequirementsHandler(ICurrentContext currentContext, IHttpContextAccessor httpContextAccessor)
: OrganizationRequirementHandler(currentContext, httpContextAccessor)
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
OrganizationRequirementAttribute requirement)
{
var authorized = requirement switch
{
ManageUsersRequirementAttribute => Organization is
{ Type: OrganizationUserType.Owner or OrganizationUserType.Admin } or
{ Permissions.ManageUsers: true },
_ => false
};
if (authorized)
{
context.Succeed(requirement);
} }
return Task.CompletedTask; return Task.CompletedTask;