mirror of
https://github.com/bitwarden/server.git
synced 2025-04-05 05:00:19 -05:00
Move to api project, create new context class
This commit is contained in:
parent
b840e2e318
commit
3d83e4b5a7
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
namespace Bit.Api.AdminConsole.Authorization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An attribute which requires authorization using the specified requirement.
|
/// An attribute which requires authorization using the specified requirement.
|
@ -1,9 +1,10 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Api.AdminConsole.Context;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
namespace Bit.Api.AdminConsole.Authorization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A requirement that implements this interface will be handled by <see cref="OrganizationRequirementHandler"/>,
|
/// A requirement that implements this interface will be handled by <see cref="OrganizationRequirementHandler"/>,
|
||||||
@ -13,6 +14,8 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IOrganizationRequirement : IAuthorizationRequirement
|
public interface IOrganizationRequirement : IAuthorizationRequirement
|
||||||
{
|
{
|
||||||
// TODO: avoid injecting all of ICurrentContext?
|
public Task<bool> AuthorizeAsync(
|
||||||
public Task<bool> AuthorizeAsync(Guid organizationId, CurrentContextOrganization? organizationClaims, ICurrentContext currentContext);
|
Guid organizationId,
|
||||||
|
CurrentContextOrganization? organizationClaims,
|
||||||
|
IProviderOrganizationContext providerOrganizationContext);
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Api.AdminConsole.Context;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
namespace Bit.Api.AdminConsole.Authorization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles any requirement that implements <see cref="IOrganizationRequirement"/>.
|
/// Handles any requirement that implements <see cref="IOrganizationRequirement"/>.
|
||||||
@ -13,7 +13,10 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="currentContext"></param>
|
/// <param name="currentContext"></param>
|
||||||
/// <param name="httpContextAccessor"></param>
|
/// <param name="httpContextAccessor"></param>
|
||||||
public class OrganizationRequirementHandler(ICurrentContext currentContext, IHttpContextAccessor httpContextAccessor)
|
public class OrganizationRequirementHandler(
|
||||||
|
ICurrentContext currentContext,
|
||||||
|
IProviderOrganizationContext providerOrganizationContext,
|
||||||
|
IHttpContextAccessor httpContextAccessor)
|
||||||
: AuthorizationHandler<IOrganizationRequirement>
|
: AuthorizationHandler<IOrganizationRequirement>
|
||||||
{
|
{
|
||||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IOrganizationRequirement requirement)
|
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IOrganizationRequirement requirement)
|
||||||
@ -24,9 +27,9 @@ public class OrganizationRequirementHandler(ICurrentContext currentContext, IHtt
|
|||||||
throw new Exception("No organizationId found in route. IOrganizationRequirement cannot be used on this endpoint.");
|
throw new Exception("No organizationId found in route. IOrganizationRequirement cannot be used on this endpoint.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var organization = currentContext.GetOrganization(organizationId.Value);
|
var organizationClaims = currentContext.GetOrganization(organizationId.Value);
|
||||||
|
|
||||||
var authorized = await requirement.AuthorizeAsync(organizationId.Value, organization, currentContext);
|
var authorized = await requirement.AuthorizeAsync(organizationId.Value, organizationClaims, providerOrganizationContext);
|
||||||
|
|
||||||
if (authorized)
|
if (authorized)
|
||||||
{
|
{
|
@ -1,9 +1,6 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Http;
|
namespace Bit.Api.AdminConsole.Authorization;
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|
||||||
|
|
||||||
public static class OrganizationRequirementHelpers
|
public static class OrganizationRequirementHelpers
|
||||||
{
|
{
|
@ -0,0 +1,19 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Api.AdminConsole.Context;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
|
||||||
|
namespace Bit.Api.AdminConsole.Authorization.Requirements;
|
||||||
|
|
||||||
|
public class ManageUsersRequirement : IOrganizationRequirement
|
||||||
|
{
|
||||||
|
public async Task<bool> AuthorizeAsync(
|
||||||
|
Guid organizationId,
|
||||||
|
CurrentContextOrganization? organizationClaims,
|
||||||
|
IProviderOrganizationContext providerOrganizationContext)
|
||||||
|
=> organizationClaims is
|
||||||
|
{ Type: OrganizationUserType.Owner or OrganizationUserType.Admin } or
|
||||||
|
{ Permissions.ManageUsers: true }
|
||||||
|
|| await providerOrganizationContext.ProviderUserForOrgAsync(organizationId);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Api.AdminConsole.Context;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
|
||||||
|
namespace Bit.Api.AdminConsole.Authorization.Requirements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requires that the user is a member of the organization or a provider for the organization.
|
||||||
|
/// </summary>
|
||||||
|
public class MemberOrProviderRequirement : IOrganizationRequirement
|
||||||
|
{
|
||||||
|
public async Task<bool> AuthorizeAsync(
|
||||||
|
Guid organizationId,
|
||||||
|
CurrentContextOrganization? organizationClaims,
|
||||||
|
IProviderOrganizationContext providerOrganizationContext)
|
||||||
|
=> organizationClaims is not null || await providerOrganizationContext.ProviderUserForOrgAsync(organizationId);
|
||||||
|
}
|
12
src/Api/AdminConsole/Context/IProviderOrganizationContext.cs
Normal file
12
src/Api/AdminConsole/Context/IProviderOrganizationContext.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Bit.Api.AdminConsole.Context;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current context for the relationship between ProviderUsers and Organizations that they manage.
|
||||||
|
/// </summary>
|
||||||
|
public interface IProviderOrganizationContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the current user is a ProviderUser for the specified organization, false otherwise.
|
||||||
|
/// </summary>
|
||||||
|
Task<bool> ProviderUserForOrgAsync(Guid orgId);
|
||||||
|
}
|
19
src/Api/AdminConsole/Context/ProviderOrganizationContext.cs
Normal file
19
src/Api/AdminConsole/Context/ProviderOrganizationContext.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Bit.Core.Context;
|
||||||
|
|
||||||
|
namespace Bit.Api.AdminConsole.Context;
|
||||||
|
|
||||||
|
public class ProviderOrganizationContext(ICurrentContext currentContext) : IProviderOrganizationContext
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<bool> ProviderUserForOrgAsync(Guid orgId)
|
||||||
|
{
|
||||||
|
// If the user doesn't have any ProviderUser claims (in relation to the provider), they can't have a provider
|
||||||
|
// relationship to any organization.
|
||||||
|
if (currentContext.Providers.Count == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await currentContext.ProviderUserForOrgAsync(orgId);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
using Bit.Api.AdminConsole.Authorization;
|
||||||
|
using Bit.Api.AdminConsole.Authorization.Requirements;
|
||||||
|
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
||||||
using Bit.Api.AdminConsole.Models.Response.Organizations;
|
using Bit.Api.AdminConsole.Models.Response.Organizations;
|
||||||
using Bit.Api.Models.Request.Organizations;
|
using Bit.Api.Models.Request.Organizations;
|
||||||
using Bit.Api.Models.Response;
|
using Bit.Api.Models.Response;
|
||||||
@ -6,11 +8,9 @@ using Bit.Api.Vault.AuthorizationHandlers.Collections;
|
|||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Enums;
|
using Bit.Core.AdminConsole.Enums;
|
||||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures;
|
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Auth.Enums;
|
using Bit.Core.Auth.Enums;
|
||||||
using Bit.Core.Auth.Repositories;
|
using Bit.Core.Auth.Repositories;
|
||||||
|
@ -7,6 +7,7 @@ using Stripe;
|
|||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Duende.IdentityModel;
|
using Duende.IdentityModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Bit.Api.AdminConsole.Context;
|
||||||
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
||||||
using Bit.Api.Auth.Models.Request;
|
using Bit.Api.Auth.Models.Request;
|
||||||
using Bit.Api.KeyManagement.Validators;
|
using Bit.Api.KeyManagement.Validators;
|
||||||
@ -84,6 +85,7 @@ public class Startup
|
|||||||
|
|
||||||
// Context
|
// Context
|
||||||
services.AddScoped<ICurrentContext, CurrentContext>();
|
services.AddScoped<ICurrentContext, CurrentContext>();
|
||||||
|
services.AddScoped<IProviderOrganizationContext, ProviderOrganizationContext>();
|
||||||
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
// Caching
|
// Caching
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Api.Tools.Authorization;
|
using Bit.Api.AdminConsole.Authorization;
|
||||||
|
using Bit.Api.Tools.Authorization;
|
||||||
using Bit.Api.Vault.AuthorizationHandlers.Collections;
|
using Bit.Api.Vault.AuthorizationHandlers.Collections;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Groups.Authorization;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Groups.Authorization;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|
||||||
using Bit.Core.IdentityServer;
|
using Bit.Core.IdentityServer;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
|
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|
||||||
using Bit.Core.Context;
|
|
||||||
using Bit.Core.Enums;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures;
|
|
||||||
|
|
||||||
public class ManageUsersRequirement : IOrganizationRequirement
|
|
||||||
{
|
|
||||||
public async Task<bool> AuthorizeAsync(Guid organizationId, CurrentContextOrganization? organizationClaims, ICurrentContext currentContext)
|
|
||||||
=> organizationClaims is
|
|
||||||
{ Type: OrganizationUserType.Owner or OrganizationUserType.Admin } or
|
|
||||||
{ Permissions.ManageUsers: true }
|
|
||||||
|| await currentContext.ProviderUserForOrgAsync(organizationId);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
|
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
|
||||||
using Bit.Core.Context;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Requires that the user is a member of the organization or a provider for the organization.
|
|
||||||
/// </summary>
|
|
||||||
public class MemberOrProviderRequirement : IOrganizationRequirement
|
|
||||||
{
|
|
||||||
public async Task<bool> AuthorizeAsync(Guid organizationId, CurrentContextOrganization? organizationClaims, ICurrentContext currentContext)
|
|
||||||
=> organizationClaims is not null || await currentContext.ProviderUserForOrgAsync(organizationId);
|
|
||||||
}
|
|
@ -22,6 +22,7 @@ public interface ICurrentContext
|
|||||||
string IpAddress { get; set; }
|
string IpAddress { get; set; }
|
||||||
string CountryName { get; set; }
|
string CountryName { get; set; }
|
||||||
List<CurrentContextOrganization> Organizations { get; set; }
|
List<CurrentContextOrganization> Organizations { get; set; }
|
||||||
|
List<CurrentContextProvider> Providers { get; set; }
|
||||||
Guid? InstallationId { get; set; }
|
Guid? InstallationId { get; set; }
|
||||||
Guid? OrganizationId { get; set; }
|
Guid? OrganizationId { get; set; }
|
||||||
IdentityClientType IdentityClientType { get; set; }
|
IdentityClientType IdentityClientType { get; set; }
|
||||||
@ -59,6 +60,7 @@ public interface ICurrentContext
|
|||||||
Task<bool> EditSubscription(Guid orgId);
|
Task<bool> EditSubscription(Guid orgId);
|
||||||
Task<bool> EditPaymentMethods(Guid orgId);
|
Task<bool> EditPaymentMethods(Guid orgId);
|
||||||
Task<bool> ViewBillingHistory(Guid orgId);
|
Task<bool> ViewBillingHistory(Guid orgId);
|
||||||
|
[Obsolete("Use IProviderOrganizationContext.ProviderUserForOrgAsync instead.")]
|
||||||
Task<bool> ProviderUserForOrgAsync(Guid orgId);
|
Task<bool> ProviderUserForOrgAsync(Guid orgId);
|
||||||
bool ProviderProviderAdmin(Guid providerId);
|
bool ProviderProviderAdmin(Guid providerId);
|
||||||
bool ProviderUser(Guid providerId);
|
bool ProviderUser(Guid providerId);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user