mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
[SM-949] Add endpoint to fetch events by service account (#3336)
* Add ability to fetch events by service account * Extract GetDateRange into ApiHelpers util * Add dapper implementation * Add EF repo implementation * Add authz handler case * unit + integration tests for controller * swap to read check * Adding comments * Fix integration tests from merge * Enabled SM events controller for self-hosting
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.Utilities;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
@ -41,7 +42,7 @@ public class EventsController : Controller
|
||||
public async Task<ListResponseModel<EventResponseModel>> GetUser(
|
||||
[FromQuery] DateTime? start = null, [FromQuery] DateTime? end = null, [FromQuery] string continuationToken = null)
|
||||
{
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var result = await _eventRepository.GetManyByUserAsync(userId, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
@ -75,7 +76,7 @@ public class EventsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var result = await _eventRepository.GetManyByCipherAsync(cipher, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
var responses = result.Data.Select(e => new EventResponseModel(e));
|
||||
@ -92,7 +93,7 @@ public class EventsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var result = await _eventRepository.GetManyByOrganizationAsync(orgId, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
var responses = result.Data.Select(e => new EventResponseModel(e));
|
||||
@ -110,7 +111,7 @@ public class EventsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var result = await _eventRepository.GetManyByOrganizationActingUserAsync(organizationUser.OrganizationId,
|
||||
organizationUser.UserId.Value, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
@ -127,7 +128,7 @@ public class EventsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var result = await _eventRepository.GetManyByProviderAsync(providerId, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
var responses = result.Data.Select(e => new EventResponseModel(e));
|
||||
@ -145,33 +146,11 @@ public class EventsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = GetDateRange(start, end);
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
var result = await _eventRepository.GetManyByProviderActingUserAsync(providerUser.ProviderId,
|
||||
providerUser.UserId.Value, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
var responses = result.Data.Select(e => new EventResponseModel(e));
|
||||
return new ListResponseModel<EventResponseModel>(responses, result.ContinuationToken);
|
||||
}
|
||||
|
||||
private Tuple<DateTime, DateTime> GetDateRange(DateTime? start, DateTime? end)
|
||||
{
|
||||
if (!end.HasValue || !start.HasValue)
|
||||
{
|
||||
end = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
|
||||
start = DateTime.UtcNow.Date.AddDays(-30);
|
||||
}
|
||||
else if (start.Value > end.Value)
|
||||
{
|
||||
var newEnd = start;
|
||||
start = end;
|
||||
end = newEnd;
|
||||
}
|
||||
|
||||
if ((end.Value - start.Value) > TimeSpan.FromDays(367))
|
||||
{
|
||||
throw new BadRequestException("Range too large.");
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, DateTime>(start.Value, end.Value);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.Utilities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.AuthorizationRequirements;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.SecretsManager.Controllers;
|
||||
|
||||
[Authorize("secrets")]
|
||||
public class SecretsManagerEventsController : Controller
|
||||
{
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IEventRepository _eventRepository;
|
||||
private readonly IServiceAccountRepository _serviceAccountRepository;
|
||||
|
||||
public SecretsManagerEventsController(
|
||||
IEventRepository eventRepository,
|
||||
IServiceAccountRepository serviceAccountRepository,
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_authorizationService = authorizationService;
|
||||
_serviceAccountRepository = serviceAccountRepository;
|
||||
_eventRepository = eventRepository;
|
||||
}
|
||||
|
||||
[HttpGet("sm/events/service-accounts/{serviceAccountId}")]
|
||||
public async Task<ListResponseModel<EventResponseModel>> GetServiceAccountEventsAsync(Guid serviceAccountId,
|
||||
[FromQuery] DateTime? start = null, [FromQuery] DateTime? end = null,
|
||||
[FromQuery] string continuationToken = null)
|
||||
{
|
||||
var serviceAccount = await _serviceAccountRepository.GetByIdAsync(serviceAccountId);
|
||||
var authorizationResult =
|
||||
await _authorizationService.AuthorizeAsync(User, serviceAccount, ServiceAccountOperations.ReadEvents);
|
||||
|
||||
if (!authorizationResult.Succeeded)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var dateRange = ApiHelpers.GetDateRange(start, end);
|
||||
|
||||
var result = await _eventRepository.GetManyByOrganizationServiceAccountAsync(serviceAccount.OrganizationId,
|
||||
serviceAccount.Id, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = continuationToken });
|
||||
var responses = result.Data.Select(e => new EventResponseModel(e));
|
||||
return new ListResponseModel<EventResponseModel>(responses, result.ContinuationToken);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using Azure.Messaging.EventGrid;
|
||||
using Azure.Messaging.EventGrid.SystemEvents;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@ -69,4 +70,35 @@ public static class ApiHelpers
|
||||
|
||||
return new OkObjectResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates and returns a date range. Currently used for fetching events.
|
||||
/// </summary>
|
||||
/// <param name="start">start date and time</param>
|
||||
/// <param name="end">end date and time</param>
|
||||
/// <remarks>
|
||||
/// If start or end are null, will return a range of the last 30 days.
|
||||
/// If a time span greater than 367 days is passed will throw BadRequestException.
|
||||
/// </remarks>
|
||||
public static Tuple<DateTime, DateTime> GetDateRange(DateTime? start, DateTime? end)
|
||||
{
|
||||
if (!end.HasValue || !start.HasValue)
|
||||
{
|
||||
end = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
|
||||
start = DateTime.UtcNow.Date.AddDays(-30);
|
||||
}
|
||||
else if (start.Value > end.Value)
|
||||
{
|
||||
var newEnd = start;
|
||||
start = end;
|
||||
end = newEnd;
|
||||
}
|
||||
|
||||
if ((end.Value - start.Value) > TimeSpan.FromDays(367))
|
||||
{
|
||||
throw new BadRequestException("Range too large.");
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, DateTime>(start.Value, end.Value);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user