1
0
mirror of https://github.com/bitwarden/server.git synced 2025-01-10 20:07:56 +01:00

event sql table and repo

This commit is contained in:
Kyle Spearrin 2017-12-12 14:22:22 -05:00
parent 7b359053d6
commit ce1680a009
11 changed files with 225 additions and 19 deletions

View File

@ -3,7 +3,7 @@ using Bit.Core.Enums;
namespace Bit.Core.Models.Data namespace Bit.Core.Models.Data
{ {
public class Event : IEvent public class EventMessage : IEvent
{ {
public DateTime Date { get; set; } public DateTime Date { get; set; }
public EventType Type { get; set; } public EventType Type { get; set; }

View File

@ -5,7 +5,6 @@ namespace Bit.Core.Models.Data
{ {
public interface IEvent public interface IEvent
{ {
DateTime Date { get; set; }
EventType Type { get; set; } EventType Type { get; set; }
Guid? UserId { get; set; } Guid? UserId { get; set; }
Guid? OrganizationId { get; set; } Guid? OrganizationId { get; set; }
@ -14,5 +13,6 @@ namespace Bit.Core.Models.Data
Guid? GroupId { get; set; } Guid? GroupId { get; set; }
Guid? OrganizationUserId { get; set; } Guid? OrganizationUserId { get; set; }
Guid? ActingUserId { get; set; } Guid? ActingUserId { get; set; }
DateTime Date { get; set; }
} }
} }

View File

@ -0,0 +1,41 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Table
{
public class Event : ITableObject<Guid>, IEvent
{
public Event() { }
public Event(IEvent e)
{
Date = e.Date;
Type = e.Type;
UserId = e.UserId;
OrganizationId = e.OrganizationId;
CipherId = e.CipherId;
CollectionId = e.CollectionId;
GroupId = e.GroupId;
OrganizationUserId = e.OrganizationUserId;
ActingUserId = e.ActingUserId;
}
public Guid Id { get; set; }
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ActingUserId { get; set; }
public void SetNewId()
{
Id = CoreHelpers.GenerateComb();
}
}
}

View File

@ -8,7 +8,7 @@ namespace Bit.Core.Repositories
public interface IEventRepository public interface IEventRepository
{ {
Task<ICollection<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate); Task<ICollection<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate);
Task CreateAsync(IEvent entity); Task CreateAsync(IEvent e);
Task CreateManyAsync(IList<IEvent> entities); Task CreateManyAsync(IList<IEvent> e);
} }
} }

View File

@ -392,8 +392,7 @@ namespace Bit.Core.Repositories.SqlServer
{ {
if(folders.Any()) if(folders.Any())
{ {
using(var bulkCopy = new SqlBulkCopy(connection, using(var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, transaction))
SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.FireTriggers, transaction))
{ {
bulkCopy.DestinationTableName = "[dbo].[Folder]"; bulkCopy.DestinationTableName = "[dbo].[Folder]";
var dataTable = BuildFoldersTable(folders); var dataTable = BuildFoldersTable(folders);
@ -401,8 +400,7 @@ namespace Bit.Core.Repositories.SqlServer
} }
} }
using(var bulkCopy = new SqlBulkCopy(connection, using(var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, transaction))
SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.FireTriggers, transaction))
{ {
bulkCopy.DestinationTableName = "[dbo].[Cipher]"; bulkCopy.DestinationTableName = "[dbo].[Cipher]";
var dataTable = BuildCiphersTable(ciphers); var dataTable = BuildCiphersTable(ciphers);

View File

@ -0,0 +1,115 @@
using System;
using Bit.Core.Models.Table;
using System.Threading.Tasks;
using System.Collections.Generic;
using Bit.Core.Models.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Data;
namespace Bit.Core.Repositories.SqlServer
{
public class EventRepository : Repository<Event, Guid>, IEventRepository
{
public EventRepository(GlobalSettings globalSettings)
: this(globalSettings.SqlServer.ConnectionString)
{ }
public EventRepository(string connectionString)
: base(connectionString)
{ }
public Task<ICollection<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate)
{
// TODO
throw new NotImplementedException();
}
public async Task CreateAsync(IEvent e)
{
if(!(e is Event ev))
{
ev = new Event(e);
}
await base.CreateAsync(ev);
}
public async Task CreateManyAsync(IList<IEvent> entities)
{
if(!entities.Any())
{
return;
}
using(var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using(var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, null))
{
bulkCopy.DestinationTableName = "[dbo].[Event]";
var dataTable = BuildEventsTable(entities.Select(e => e is Event ? e as Event : new Event(e)));
await bulkCopy.WriteToServerAsync(dataTable);
}
}
}
private DataTable BuildEventsTable(IEnumerable<Event> events)
{
var e = events.FirstOrDefault();
if(e == null)
{
throw new ApplicationException("Must have some events to bulk import.");
}
var eventsTable = new DataTable("EventDataTable");
var idColumn = new DataColumn(nameof(e.Id), e.Id.GetType());
eventsTable.Columns.Add(idColumn);
var typeColumn = new DataColumn(nameof(e.Type), typeof(int));
eventsTable.Columns.Add(typeColumn);
var dateColumn = new DataColumn(nameof(e.Date), e.Date.GetType());
eventsTable.Columns.Add(dateColumn);
var userIdColumn = new DataColumn(nameof(e.UserId), typeof(Guid));
eventsTable.Columns.Add(userIdColumn);
var organizationIdColumn = new DataColumn(nameof(e.OrganizationId), typeof(Guid));
eventsTable.Columns.Add(organizationIdColumn);
var cipherIdColumn = new DataColumn(nameof(e.CipherId), typeof(Guid));
eventsTable.Columns.Add(cipherIdColumn);
var groupIdColumn = new DataColumn(nameof(e.GroupId), typeof(Guid));
eventsTable.Columns.Add(groupIdColumn);
var collectionIdColumn = new DataColumn(nameof(e.CollectionId), typeof(Guid));
eventsTable.Columns.Add(collectionIdColumn);
var actingUserIdColumn = new DataColumn(nameof(e.ActingUserId), typeof(Guid));
eventsTable.Columns.Add(actingUserIdColumn);
var organizationUserIdColumn = new DataColumn(nameof(e.OrganizationUserId), typeof(Guid));
eventsTable.Columns.Add(organizationUserIdColumn);
var keys = new DataColumn[1];
keys[0] = idColumn;
eventsTable.PrimaryKey = keys;
foreach(var ev in events)
{
ev.SetNewId();
var row = eventsTable.NewRow();
row[idColumn] = ev.Id;
row[typeColumn] = ev.Type;
row[dateColumn] = ev.Date;
row[userIdColumn] = ev.UserId;
row[organizationIdColumn] = ev.OrganizationId;
row[cipherIdColumn] = ev.CipherId;
row[groupIdColumn] = ev.GroupId;
row[collectionIdColumn] = ev.CollectionId;
row[actingUserIdColumn] = ev.ActingUserId;
row[organizationUserIdColumn] = ev.OrganizationUserId;
eventsTable.Rows.Add(row);
}
return eventsTable;
}
}
}

View File

@ -33,7 +33,7 @@ namespace Bit.Core.Services
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
var events = new List<IEvent> var events = new List<IEvent>
{ {
new Event new EventMessage
{ {
UserId = userId, UserId = userId,
Type = type, Type = type,
@ -44,7 +44,7 @@ namespace Bit.Core.Services
IEnumerable<IEvent> orgEvents; IEnumerable<IEvent> orgEvents;
if(_currentContext.UserId.HasValue) if(_currentContext.UserId.HasValue)
{ {
orgEvents = _currentContext.Organizations.Select(o => new Event orgEvents = _currentContext.Organizations.Select(o => new EventMessage
{ {
OrganizationId = o.Id, OrganizationId = o.Id,
UserId = userId, UserId = userId,
@ -56,7 +56,7 @@ namespace Bit.Core.Services
{ {
var orgs = await _organizationUserRepository.GetManyByUserAsync(userId); var orgs = await _organizationUserRepository.GetManyByUserAsync(userId);
orgEvents = orgs.Where(o => o.Status == OrganizationUserStatusType.Confirmed) orgEvents = orgs.Where(o => o.Status == OrganizationUserStatusType.Confirmed)
.Select(o => new Event .Select(o => new EventMessage
{ {
OrganizationId = o.Id, OrganizationId = o.Id,
UserId = userId, UserId = userId,
@ -83,7 +83,7 @@ namespace Bit.Core.Services
return; return;
} }
var e = new Event var e = new EventMessage
{ {
OrganizationId = cipher.OrganizationId, OrganizationId = cipher.OrganizationId,
UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId, UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId,
@ -97,7 +97,7 @@ namespace Bit.Core.Services
public async Task LogCollectionEventAsync(Collection collection, EventType type) public async Task LogCollectionEventAsync(Collection collection, EventType type)
{ {
var e = new Event var e = new EventMessage
{ {
OrganizationId = collection.OrganizationId, OrganizationId = collection.OrganizationId,
CollectionId = collection.Id, CollectionId = collection.Id,
@ -110,7 +110,7 @@ namespace Bit.Core.Services
public async Task LogGroupEventAsync(Group group, EventType type) public async Task LogGroupEventAsync(Group group, EventType type)
{ {
var e = new Event var e = new EventMessage
{ {
OrganizationId = group.OrganizationId, OrganizationId = group.OrganizationId,
GroupId = group.Id, GroupId = group.Id,
@ -123,7 +123,7 @@ namespace Bit.Core.Services
public async Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type) public async Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type)
{ {
var e = new Event var e = new EventMessage
{ {
OrganizationId = organizationUser.OrganizationId, OrganizationId = organizationUser.OrganizationId,
UserId = organizationUser.UserId, UserId = organizationUser.UserId,
@ -137,7 +137,7 @@ namespace Bit.Core.Services
public async Task LogOrganizationEventAsync(Organization organization, EventType type) public async Task LogOrganizationEventAsync(Organization organization, EventType type)
{ {
var e = new Event var e = new EventMessage
{ {
OrganizationId = organization.Id, OrganizationId = organization.Id,
Type = type, Type = type,

View File

@ -44,7 +44,7 @@ namespace Bit.Core.Utilities
if(globalSettings.SelfHosted) if(globalSettings.SelfHosted)
{ {
// TODO: Sql server event repo services.AddSingleton<IEventRepository, SqlServerRepos.EventRepository>();
} }
else else
{ {

View File

@ -42,13 +42,13 @@ namespace Bit.EventsProcessor
var token = JToken.Parse(message); var token = JToken.Parse(message);
if(token is JArray) if(token is JArray)
{ {
var events = token.ToObject<List<Event>>() var events = token.ToObject<List<EventMessage>>()
.Select(e => new EventTableEntity(e) as IEvent).ToList(); .Select(e => new EventTableEntity(e) as IEvent).ToList();
await _eventWriteService.CreateManyAsync(events); await _eventWriteService.CreateManyAsync(events);
} }
else if(token is JObject) else if(token is JObject)
{ {
var e = token.ToObject<Event>(); var e = token.ToObject<EventMessage>();
await _eventWriteService.CreateAsync(new EventTableEntity(e)); await _eventWriteService.CreateAsync(new EventTableEntity(e));
} }
} }

View File

@ -0,0 +1,39 @@
CREATE PROCEDURE [dbo].[Event_Create]
@Id UNIQUEIDENTIFIER,
@Type INT,
@UserId UNIQUEIDENTIFIER,
@OrganizationId UNIQUEIDENTIFIER,
@CipherId UNIQUEIDENTIFIER,
@CollectionId UNIQUEIDENTIFIER,
@GroupId UNIQUEIDENTIFIER,
@OrganizationUserId UNIQUEIDENTIFIER,
@Date DATETIME2(7)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[Event]
(
[Id],
[Type],
[UserId],
[OrganizationId],
[CipherId],
[CollectionId],
[GroupId],
[OrganizationUserId],
[Date]
)
VALUES
(
@Id,
@Type,
@UserId,
@OrganizationId,
@CipherId,
@CollectionId,
@GroupId,
@OrganizationUserId,
@Date
)
END

View File

@ -0,0 +1,13 @@
CREATE TABLE [dbo].[Event] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[Type] INT NOT NULL,
[UserId] UNIQUEIDENTIFIER NULL,
[OrganizationId] UNIQUEIDENTIFIER NULL,
[CipherId] UNIQUEIDENTIFIER NULL,
[CollectionId] UNIQUEIDENTIFIER NULL,
[GroupId] UNIQUEIDENTIFIER NULL,
[OrganizationUserId] UNIQUEIDENTIFIER NULL,
[Date] DATETIME2 (7) NOT NULL,
CONSTRAINT [PK_Event] PRIMARY KEY CLUSTERED ([Id] ASC)
);