1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-16 09:05:44 -05:00

events apis

This commit is contained in:
Kyle Spearrin 2019-03-07 09:13:39 -05:00
parent 80e5258624
commit 62503068c6
3 changed files with 206 additions and 0 deletions

View File

@ -0,0 +1,73 @@
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Bit.Core;
using Bit.Core.Models.Api.Public;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Api.Public.Controllers
{
[Route("public/events")]
[Authorize("Organization")]
public class EventsController : Controller
{
private readonly IEventRepository _eventRepository;
private readonly ICipherRepository _cipherRepository;
private readonly CurrentContext _currentContext;
public EventsController(
IEventRepository eventRepository,
ICipherRepository cipherRepository,
CurrentContext currentContext)
{
_eventRepository = eventRepository;
_cipherRepository = cipherRepository;
_currentContext = currentContext;
}
/// <summary>
/// List all events.
/// </summary>
/// <remarks>
/// Returns a filtered list of your organization's event logs, paged by a continuation token.
/// If no filters are provided, it will return the last 30 days of event for the organization.
/// </remarks>
[HttpGet]
[ProducesResponseType(typeof(ListResponseModel<EventResponseModel>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> List([FromQuery]EventFilterRequestModel request)
{
var dateRange = request.ToDateRange();
var result = new PagedResult<IEvent>();
if(request.ActingUserId.HasValue)
{
result = await _eventRepository.GetManyByOrganizationActingUserAsync(
_currentContext.OrganizationId.Value, request.ActingUserId.Value, dateRange.Item1, dateRange.Item2,
new PageOptions { ContinuationToken = request.ContinuationToken });
}
else if(request.ItemId.HasValue)
{
var cipher = await _cipherRepository.GetByIdAsync(request.ItemId.Value);
if(cipher != null && cipher.OrganizationId == _currentContext.OrganizationId.Value)
{
result = await _eventRepository.GetManyByCipherAsync(
cipher, dateRange.Item1, dateRange.Item2,
new PageOptions { ContinuationToken = request.ContinuationToken });
}
}
else
{
result = await _eventRepository.GetManyByOrganizationAsync(
_currentContext.OrganizationId.Value, dateRange.Item1, dateRange.Item2,
new PageOptions { ContinuationToken = request.ContinuationToken });
}
var eventResponses = result.Data.Select(e => new EventResponseModel(e));
var response = new ListResponseModel<EventResponseModel>(eventResponses);
return new JsonResult(response);
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using Bit.Core.Exceptions;
namespace Bit.Core.Models.Api.Public
{
public class EventFilterRequestModel
{
/// <summary>
/// The start date. Must be less than the end date.
/// </summary>
public DateTime? Start { get; set; }
/// <summary>
/// The end date. Must be greater than the start date.
/// </summary>
public DateTime? End { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
public Guid? ItemId { get; set; }
/// <summary>
/// A cursor for use in pagination.
/// </summary>
public string ContinuationToken { get; set; }
public Tuple<DateTime, DateTime> ToDateRange()
{
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("Date range must be < 367 days.");
}
return new Tuple<DateTime, DateTime>(Start.Value, End.Value);
}
}
}

View File

@ -0,0 +1,82 @@
using System;
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Core.Models.Api.Public
{
/// <summary>
/// An event log.
/// </summary>
public class EventResponseModel : IResponseModel
{
public EventResponseModel(IEvent ev)
{
if(ev == null)
{
throw new ArgumentNullException(nameof(ev));
}
Type = ev.Type;
ItemId = ev.CipherId;
CollectionId = ev.CollectionId;
GroupId = ev.GroupId;
MemberId = ev.OrganizationUserId;
ActingUserId = ev.ActingUserId;
Date = ev.Date;
Device = ev.DeviceType;
IpAddress = ev.IpAddress;
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>event</example>
[Required]
public string Object => "event";
/// <summary>
/// The type of event.
/// </summary>
[Required]
public EventType Type { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
/// <example>3767a302-8208-4dc6-b842-030428a1cfad</example>
public Guid? ItemId { get; set; }
/// <summary>
/// The unique identifier of the related collection that the event describes.
/// </summary>
/// <example>bce212a4-25f3-4888-8a0a-4c5736d851e0</example>
public Guid? CollectionId { get; set; }
/// <summary>
/// The unique identifier of the related group that the event describes.
/// </summary>
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
public Guid? GroupId { get; set; }
/// <summary>
/// The unique identifier of the related member that the event describes.
/// </summary>
/// <example>e68b8629-85eb-4929-92c0-b84464976ba4</example>
public Guid? MemberId { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
/// <example>a2549f79-a71f-4eb9-9234-eb7247333f94</example>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The date/timestamp when the event occurred.
/// </summary>
[Required]
public DateTime Date { get; set; }
/// <summary>
/// The type of device used by the acting user when the event occurred.
/// </summary>
public DeviceType? Device { get; set; }
/// <summary>
/// The IP address of the acting user.
/// </summary>
/// <example>172.16.254.1</example>
public string IpAddress { get; set; }
}
}