mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
[SM-788] Extract authorization from secret delete command (#3003)
* Extract authorization from secret delete command
This commit is contained in:
@ -41,6 +41,9 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
case not null when requirement == SecretOperations.Update:
|
||||
await CanUpdateSecretAsync(context, requirement, resource);
|
||||
break;
|
||||
case not null when requirement == SecretOperations.Delete:
|
||||
await CanDeleteSecretAsync(context, requirement, resource);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unsupported operation requirement type provided.", nameof(requirement));
|
||||
}
|
||||
@ -120,4 +123,22 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CanDeleteSecretAsync(AuthorizationHandlerContext context,
|
||||
SecretOperationRequirement requirement, Secret resource)
|
||||
{
|
||||
var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(context.User, resource.OrganizationId);
|
||||
|
||||
if (accessClient == AccessClientType.ServiceAccount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var access = await _secretRepository.AccessToSecretAsync(resource.Id, userId, accessClient);
|
||||
|
||||
if (access.Write)
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.SecretsManager.Commands.Secrets.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.Secrets.Interfaces;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
|
||||
@ -9,73 +6,16 @@ namespace Bit.Commercial.Core.SecretsManager.Commands.Secrets;
|
||||
|
||||
public class DeleteSecretCommand : IDeleteSecretCommand
|
||||
{
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly ISecretRepository _secretRepository;
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
|
||||
public DeleteSecretCommand(ISecretRepository secretRepository, IProjectRepository projectRepository, ICurrentContext currentContext)
|
||||
public DeleteSecretCommand(ISecretRepository secretRepository)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_secretRepository = secretRepository;
|
||||
_projectRepository = projectRepository;
|
||||
}
|
||||
|
||||
public async Task<List<Tuple<Secret, string>>> DeleteSecrets(List<Guid> ids, Guid userId)
|
||||
public async Task DeleteSecrets(IEnumerable<Secret> secrets)
|
||||
{
|
||||
var secrets = (await _secretRepository.GetManyByIds(ids)).ToList();
|
||||
|
||||
if (secrets.Any() != true)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
// Ensure all secrets belongs to the same organization
|
||||
var organizationId = secrets.First().OrganizationId;
|
||||
if (secrets.Any(secret => secret.OrganizationId != organizationId))
|
||||
{
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
if (!_currentContext.AccessSecretsManager(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var orgAdmin = await _currentContext.OrganizationAdmin(organizationId);
|
||||
var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin);
|
||||
|
||||
var results = new List<Tuple<Secret, string>>();
|
||||
var deleteIds = new List<Guid>();
|
||||
|
||||
foreach (var secret in secrets)
|
||||
{
|
||||
var hasAccess = orgAdmin;
|
||||
|
||||
if (secret.Projects != null && secret.Projects?.Count > 0)
|
||||
{
|
||||
var projectId = secret.Projects.First().Id;
|
||||
hasAccess = (await _projectRepository.AccessToProjectAsync(projectId, userId, accessClient)).Write;
|
||||
}
|
||||
|
||||
if (!hasAccess || accessClient == AccessClientType.ServiceAccount)
|
||||
{
|
||||
results.Add(new Tuple<Secret, string>(secret, "access denied"));
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteIds.Add(secret.Id);
|
||||
results.Add(new Tuple<Secret, string>(secret, ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (deleteIds.Count > 0)
|
||||
{
|
||||
await _secretRepository.SoftDeleteManyByIdAsync(deleteIds);
|
||||
}
|
||||
|
||||
return results;
|
||||
await _secretRepository.SoftDeleteManyByIdAsync(secrets.Select(s => s.Id));
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user