mirror of
https://github.com/bitwarden/server.git
synced 2025-05-31 08:10:32 -05:00
wip
This commit is contained in:
parent
e7abb07d19
commit
e9222e7fce
@ -6,6 +6,7 @@ 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.Organizations.Authorization;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.RestoreUser.v1;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.RestoreUser.v1;
|
||||||
@ -63,6 +64,7 @@ public class OrganizationUsersController : Controller
|
|||||||
private readonly IPricingClient _pricingClient;
|
private readonly IPricingClient _pricingClient;
|
||||||
private readonly IConfirmOrganizationUserCommand _confirmOrganizationUserCommand;
|
private readonly IConfirmOrganizationUserCommand _confirmOrganizationUserCommand;
|
||||||
private readonly IRestoreOrganizationUserCommand _restoreOrganizationUserCommand;
|
private readonly IRestoreOrganizationUserCommand _restoreOrganizationUserCommand;
|
||||||
|
private readonly IInitPendingOrganizationCommand _initPendingOrganizationCommand;
|
||||||
|
|
||||||
public OrganizationUsersController(
|
public OrganizationUsersController(
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
@ -313,7 +315,13 @@ public class OrganizationUsersController : Controller
|
|||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _organizationService.InitPendingOrganization(user.Id, orgId, organizationUserId, model.Keys.PublicKey, model.Keys.EncryptedPrivateKey, model.CollectionName);
|
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new OrganizationScope(orgId), OrganizationOperations.Update);
|
||||||
|
if (!authorizationResult.Succeeded)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _initPendingOrganizationCommand.InitPendingOrganizationAsync(user.Id, orgId, organizationUserId, model.Keys.PublicKey, model.Keys.EncryptedPrivateKey, model.CollectionName);
|
||||||
await _acceptOrgUserCommand.AcceptOrgUserByEmailTokenAsync(organizationUserId, user, model.Token, _userService);
|
await _acceptOrgUserCommand.AcceptOrgUserByEmailTokenAsync(organizationUserId, user, model.Token, _userService);
|
||||||
await _confirmOrganizationUserCommand.ConfirmUserAsync(orgId, organizationUserId, model.Key, user.Id);
|
await _confirmOrganizationUserCommand.ConfirmUserAsync(orgId, organizationUserId, model.Key, user.Id);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Authorization;
|
||||||
|
|
||||||
|
public class OrganizationAuthorizationHandler
|
||||||
|
: AuthorizationHandler<OrganizationOperationRequirement, OrganizationScope>
|
||||||
|
{
|
||||||
|
private readonly ICurrentContext _currentContext;
|
||||||
|
|
||||||
|
public OrganizationAuthorizationHandler(ICurrentContext currentContext)
|
||||||
|
{
|
||||||
|
_currentContext = currentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
|
||||||
|
OrganizationOperationRequirement requirement, OrganizationScope organizationScope)
|
||||||
|
{
|
||||||
|
var authorized = false;
|
||||||
|
|
||||||
|
switch (requirement)
|
||||||
|
{
|
||||||
|
case not null when requirement.Name == nameof(OrganizationOperations.Update):
|
||||||
|
authorized = await CanUpdateAsync(organizationScope);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authorized)
|
||||||
|
{
|
||||||
|
context.Succeed(requirement!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CanUpdateAsync(Guid organizationId)
|
||||||
|
{
|
||||||
|
var organization = _currentContext.GetOrganization(organizationId);
|
||||||
|
if (organization != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow provider users to update organization data if they are a provider for the target organization
|
||||||
|
return await _currentContext.ProviderUserForOrgAsync(organizationId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||||
|
|
||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Authorization;
|
||||||
|
|
||||||
|
public class OrganizationOperationRequirement : OperationAuthorizationRequirement;
|
||||||
|
|
||||||
|
public static class OrganizationOperations
|
||||||
|
{
|
||||||
|
public static OrganizationOperationRequirement Update = new() { Name = nameof(Update) };
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||||
|
|
||||||
|
public class InitPendingOrganizationCommand : IInitPendingOrganizationCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IOrganizationService _organizationService;
|
||||||
|
private readonly ICollectionRepository _collectionRepository;
|
||||||
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
|
|
||||||
|
public InitPendingOrganizationCommand(
|
||||||
|
IOrganizationService organizationService,
|
||||||
|
ICollectionRepository collectionRepository,
|
||||||
|
IOrganizationRepository organizationRepository
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_organizationService = organizationService;
|
||||||
|
_collectionRepository = collectionRepository;
|
||||||
|
_organizationRepository = organizationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitPendingOrganizationAsync(Guid userId, Guid organizationId, Guid organizationUserId, string publicKey, string privateKey, string collectionName)
|
||||||
|
{
|
||||||
|
await _organizationService.ValidateSignUpPoliciesAsync(userId);
|
||||||
|
|
||||||
|
var org = await _organizationRepository.GetByIdAsync(organizationId);
|
||||||
|
|
||||||
|
if (org.Enabled)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Organization is already enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.Status != OrganizationStatusType.Pending)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Organization is not on a Pending status.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(org.PublicKey))
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Organization already has a Public Key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(org.PrivateKey))
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Organization already has a Private Key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
org.Enabled = true;
|
||||||
|
org.Status = OrganizationStatusType.Created;
|
||||||
|
org.PublicKey = publicKey;
|
||||||
|
org.PrivateKey = privateKey;
|
||||||
|
|
||||||
|
await _organizationService.UpdateAsync(org);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(collectionName))
|
||||||
|
{
|
||||||
|
// give the owner Can Manage access over the default collection
|
||||||
|
List<CollectionAccessSelection> defaultOwnerAccess =
|
||||||
|
[new CollectionAccessSelection { Id = organizationUserId, HidePasswords = false, ReadOnly = false, Manage = true }];
|
||||||
|
|
||||||
|
var defaultCollection = new Collection
|
||||||
|
{
|
||||||
|
Name = collectionName,
|
||||||
|
OrganizationId = org.Id
|
||||||
|
};
|
||||||
|
await _collectionRepository.CreateAsync(defaultCollection, null, defaultOwnerAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||||
|
|
||||||
|
public interface IInitPendingOrganizationCommand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Accept an invitation to initialize and join an organization created via the Admin Portal
|
||||||
|
/// </summary>
|
||||||
|
Task InitPendingOrganizationAsync(Guid userId, Guid organizationId, Guid organizationUserId, string publicKey, string privateKey, string collectionName);
|
||||||
|
}
|
@ -63,4 +63,5 @@ public interface IOrganizationService
|
|||||||
Task ValidateOrganizationUserUpdatePermissions(Guid organizationId, OrganizationUserType newType,
|
Task ValidateOrganizationUserUpdatePermissions(Guid organizationId, OrganizationUserType newType,
|
||||||
OrganizationUserType? oldType, Permissions permissions);
|
OrganizationUserType? oldType, Permissions permissions);
|
||||||
Task ValidateOrganizationCustomPermissionsEnabledAsync(Guid organizationId, OrganizationUserType newType);
|
Task ValidateOrganizationCustomPermissionsEnabledAsync(Guid organizationId, OrganizationUserType newType);
|
||||||
|
Task ValidateSignUpPoliciesAsync(Guid ownerId);
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ public class OrganizationService : IOrganizationService
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ValidateSignUpPoliciesAsync(Guid ownerId)
|
public async Task ValidateSignUpPoliciesAsync(Guid ownerId)
|
||||||
{
|
{
|
||||||
var anySingleOrgPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(ownerId, PolicyType.SingleOrg);
|
var anySingleOrgPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(ownerId, PolicyType.SingleOrg);
|
||||||
if (anySingleOrgPolicies)
|
if (anySingleOrgPolicies)
|
||||||
|
@ -9,6 +9,7 @@ using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationConnections.Interfa
|
|||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Authorization;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
|
||||||
@ -173,6 +174,7 @@ public static class OrganizationServiceCollectionExtensions
|
|||||||
|
|
||||||
services.AddScoped<IAuthorizationHandler, OrganizationUserUserMiniDetailsAuthorizationHandler>();
|
services.AddScoped<IAuthorizationHandler, OrganizationUserUserMiniDetailsAuthorizationHandler>();
|
||||||
services.AddScoped<IAuthorizationHandler, OrganizationUserUserDetailsAuthorizationHandler>();
|
services.AddScoped<IAuthorizationHandler, OrganizationUserUserDetailsAuthorizationHandler>();
|
||||||
|
services.AddScoped<IAuthorizationHandler, OrganizationAuthorizationHandler>();
|
||||||
services.AddScoped<IHasConfirmedOwnersExceptQuery, HasConfirmedOwnersExceptQuery>();
|
services.AddScoped<IHasConfirmedOwnersExceptQuery, HasConfirmedOwnersExceptQuery>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user