mirror of
https://github.com/bitwarden/server.git
synced 2024-11-22 12:15:36 +01:00
store device type and ip address on events
This commit is contained in:
parent
39f6516ca8
commit
a9f232746e
@ -3,14 +3,21 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Bit.Core.Models.Table;
|
using Bit.Core.Models.Table;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Bit.Core
|
namespace Bit.Core
|
||||||
{
|
{
|
||||||
public class CurrentContext
|
public class CurrentContext
|
||||||
{
|
{
|
||||||
|
private string _ip;
|
||||||
|
|
||||||
|
public virtual HttpContext HttpContext { get; set; }
|
||||||
public virtual Guid? UserId { get; set; }
|
public virtual Guid? UserId { get; set; }
|
||||||
public virtual User User { get; set; }
|
public virtual User User { get; set; }
|
||||||
public virtual string DeviceIdentifier { get; set; }
|
public virtual string DeviceIdentifier { get; set; }
|
||||||
|
public virtual DeviceType? DeviceType { get; set; }
|
||||||
|
public virtual string IpAddress => GetRequestIp();
|
||||||
public virtual List<CurrentContentOrganization> Organizations { get; set; } = new List<CurrentContentOrganization>();
|
public virtual List<CurrentContentOrganization> Organizations { get; set; } = new List<CurrentContentOrganization>();
|
||||||
public virtual Guid? InstallationId { get; set; }
|
public virtual Guid? InstallationId { get; set; }
|
||||||
|
|
||||||
@ -28,6 +35,31 @@ namespace Bit.Core
|
|||||||
return Organizations.Any(o => o.Id == orgId && o.Type == OrganizationUserType.Owner);
|
return Organizations.Any(o => o.Id == orgId && o.Type == OrganizationUserType.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetRequestIp()
|
||||||
|
{
|
||||||
|
if(!string.IsNullOrWhiteSpace(_ip))
|
||||||
|
{
|
||||||
|
return _ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(HttpContext == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(HttpContext.Request?.Headers?.TryGetValue("X-Forwarded-For", out StringValues forwardHeader) ?? false)
|
||||||
|
{
|
||||||
|
_ip = forwardHeader.FirstOrDefault()?.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(_ip))
|
||||||
|
{
|
||||||
|
_ip = HttpContext.Connection?.RemoteIpAddress?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ip;
|
||||||
|
}
|
||||||
|
|
||||||
public class CurrentContentOrganization
|
public class CurrentContentOrganization
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
@ -5,6 +5,14 @@ namespace Bit.Core.Models.Data
|
|||||||
{
|
{
|
||||||
public class EventMessage : IEvent
|
public class EventMessage : IEvent
|
||||||
{
|
{
|
||||||
|
public EventMessage() { }
|
||||||
|
|
||||||
|
public EventMessage(CurrentContext currentContext)
|
||||||
|
{
|
||||||
|
IpAddress = currentContext.IpAddress;
|
||||||
|
DeviceType = currentContext.DeviceType;
|
||||||
|
}
|
||||||
|
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
public EventType Type { get; set; }
|
public EventType Type { get; set; }
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
@ -14,5 +22,7 @@ namespace Bit.Core.Models.Data
|
|||||||
public Guid? GroupId { get; set; }
|
public Guid? GroupId { get; set; }
|
||||||
public Guid? OrganizationUserId { get; set; }
|
public Guid? OrganizationUserId { get; set; }
|
||||||
public Guid? ActingUserId { get; set; }
|
public Guid? ActingUserId { get; set; }
|
||||||
|
public DeviceType? DeviceType { get; set; }
|
||||||
|
public string IpAddress { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ namespace Bit.Core.Models.Data
|
|||||||
CollectionId = e.CollectionId;
|
CollectionId = e.CollectionId;
|
||||||
GroupId = e.GroupId;
|
GroupId = e.GroupId;
|
||||||
OrganizationUserId = e.OrganizationUserId;
|
OrganizationUserId = e.OrganizationUserId;
|
||||||
|
DeviceType = e.DeviceType;
|
||||||
|
IpAddress = e.IpAddress;
|
||||||
ActingUserId = e.ActingUserId;
|
ActingUserId = e.ActingUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,47 +34,58 @@ namespace Bit.Core.Models.Data
|
|||||||
public Guid? CollectionId { get; set; }
|
public Guid? CollectionId { get; set; }
|
||||||
public Guid? GroupId { get; set; }
|
public Guid? GroupId { get; set; }
|
||||||
public Guid? OrganizationUserId { get; set; }
|
public Guid? OrganizationUserId { get; set; }
|
||||||
|
public DeviceType? DeviceType { get; set; }
|
||||||
|
public string IpAddress { get; set; }
|
||||||
public Guid? ActingUserId { get; set; }
|
public Guid? ActingUserId { get; set; }
|
||||||
|
|
||||||
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
|
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
|
||||||
{
|
{
|
||||||
var result = base.WriteEntity(operationContext);
|
var result = base.WriteEntity(operationContext);
|
||||||
if(result.ContainsKey(nameof(Type)))
|
|
||||||
|
var typeName = nameof(Type);
|
||||||
|
if(result.ContainsKey(typeName))
|
||||||
{
|
{
|
||||||
result[nameof(Type)] = new EntityProperty((int)Type);
|
result[typeName] = new EntityProperty((int)Type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.Add(nameof(Type), new EntityProperty((int)Type));
|
result.Add(typeName, new EntityProperty((int)Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var deviceTypeName = nameof(DeviceType);
|
||||||
|
if(result.ContainsKey(deviceTypeName))
|
||||||
|
{
|
||||||
|
result[deviceTypeName] = new EntityProperty((int?)DeviceType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Add(deviceTypeName, new EntityProperty((int?)DeviceType));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
|
public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
|
||||||
{
|
{
|
||||||
base.ReadEntity(properties, operationContext);
|
base.ReadEntity(properties, operationContext);
|
||||||
if(properties.ContainsKey(nameof(Type)) && properties[nameof(Type)].Int32Value.HasValue)
|
|
||||||
|
var typeName = nameof(Type);
|
||||||
|
if(properties.ContainsKey(typeName) && properties[typeName].Int32Value.HasValue)
|
||||||
{
|
{
|
||||||
Type = (EventType)properties[nameof(Type)].Int32Value;
|
Type = (EventType)properties[typeName].Int32Value.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var deviceTypeName = nameof(DeviceType);
|
||||||
|
if(properties.ContainsKey(deviceTypeName) && properties[deviceTypeName].Int32Value.HasValue)
|
||||||
|
{
|
||||||
|
DeviceType = (DeviceType)properties[deviceTypeName].Int32Value.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<EventTableEntity> IndexEvent(IEvent e)
|
public static List<EventTableEntity> IndexEvent(IEvent e)
|
||||||
{
|
|
||||||
if(e.OrganizationId.HasValue)
|
|
||||||
{
|
|
||||||
return IndexOrgEvent(e);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new List<EventTableEntity> { IndexUserEvent(e) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<EventTableEntity> IndexOrgEvent(IEvent e)
|
|
||||||
{
|
{
|
||||||
var uniquifier = Guid.NewGuid();
|
var uniquifier = Guid.NewGuid();
|
||||||
var pKey = $"OrganizationId={e.OrganizationId}";
|
var pKey = e.OrganizationId.HasValue ? $"OrganizationId={e.OrganizationId}" : $"UserId={e.UserId}";
|
||||||
var dateKey = CoreHelpers.DateTimeToTableStorageKey(e.Date);
|
var dateKey = CoreHelpers.DateTimeToTableStorageKey(e.Date);
|
||||||
|
|
||||||
var entities = new List<EventTableEntity>
|
var entities = new List<EventTableEntity>
|
||||||
@ -84,7 +97,7 @@ namespace Bit.Core.Models.Data
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(e.ActingUserId.HasValue)
|
if(e.OrganizationId.HasValue && e.ActingUserId.HasValue)
|
||||||
{
|
{
|
||||||
entities.Add(new EventTableEntity(e)
|
entities.Add(new EventTableEntity(e)
|
||||||
{
|
{
|
||||||
@ -104,15 +117,5 @@ namespace Bit.Core.Models.Data
|
|||||||
|
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EventTableEntity IndexUserEvent(IEvent e)
|
|
||||||
{
|
|
||||||
var uniquifier = Guid.NewGuid();
|
|
||||||
return new EventTableEntity(e)
|
|
||||||
{
|
|
||||||
PartitionKey = $"UserId={e.UserId}",
|
|
||||||
RowKey = string.Format("Date={0}__Uniquifier={1}", CoreHelpers.DateTimeToTableStorageKey(e.Date), uniquifier)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ 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; }
|
||||||
|
DeviceType? DeviceType { get; set; }
|
||||||
|
string IpAddress { get; set; }
|
||||||
DateTime Date { get; set; }
|
DateTime Date { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ namespace Bit.Core.Models.Table
|
|||||||
CollectionId = e.CollectionId;
|
CollectionId = e.CollectionId;
|
||||||
GroupId = e.GroupId;
|
GroupId = e.GroupId;
|
||||||
OrganizationUserId = e.OrganizationUserId;
|
OrganizationUserId = e.OrganizationUserId;
|
||||||
|
DeviceType = e.DeviceType;
|
||||||
|
IpAddress = e.IpAddress;
|
||||||
ActingUserId = e.ActingUserId;
|
ActingUserId = e.ActingUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +33,8 @@ namespace Bit.Core.Models.Table
|
|||||||
public Guid? CollectionId { get; set; }
|
public Guid? CollectionId { get; set; }
|
||||||
public Guid? GroupId { get; set; }
|
public Guid? GroupId { get; set; }
|
||||||
public Guid? OrganizationUserId { get; set; }
|
public Guid? OrganizationUserId { get; set; }
|
||||||
|
public DeviceType? DeviceType { get; set; }
|
||||||
|
public string IpAddress { get; set; }
|
||||||
public Guid? ActingUserId { get; set; }
|
public Guid? ActingUserId { get; set; }
|
||||||
|
|
||||||
public void SetNewId()
|
public void SetNewId()
|
||||||
|
@ -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 EventMessage
|
new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
ActingUserId = userId,
|
ActingUserId = userId,
|
||||||
@ -45,7 +45,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 EventMessage
|
orgEvents = _currentContext.Organizations.Select(o => new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = o.Id,
|
OrganizationId = o.Id,
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
@ -58,7 +58,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 EventMessage
|
.Select(o => new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = o.OrganizationId,
|
OrganizationId = o.OrganizationId,
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
@ -87,7 +87,7 @@ namespace Bit.Core.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var e = new EventMessage
|
var e = new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = cipher.OrganizationId,
|
OrganizationId = cipher.OrganizationId,
|
||||||
UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId,
|
UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId,
|
||||||
@ -101,7 +101,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task LogCollectionEventAsync(Collection collection, EventType type)
|
public async Task LogCollectionEventAsync(Collection collection, EventType type)
|
||||||
{
|
{
|
||||||
var e = new EventMessage
|
var e = new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = collection.OrganizationId,
|
OrganizationId = collection.OrganizationId,
|
||||||
CollectionId = collection.Id,
|
CollectionId = collection.Id,
|
||||||
@ -114,7 +114,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task LogGroupEventAsync(Group group, EventType type)
|
public async Task LogGroupEventAsync(Group group, EventType type)
|
||||||
{
|
{
|
||||||
var e = new EventMessage
|
var e = new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = group.OrganizationId,
|
OrganizationId = group.OrganizationId,
|
||||||
GroupId = group.Id,
|
GroupId = group.Id,
|
||||||
@ -127,7 +127,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type)
|
public async Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type)
|
||||||
{
|
{
|
||||||
var e = new EventMessage
|
var e = new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = organizationUser.OrganizationId,
|
OrganizationId = organizationUser.OrganizationId,
|
||||||
UserId = organizationUser.UserId,
|
UserId = organizationUser.UserId,
|
||||||
@ -141,7 +141,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task LogOrganizationEventAsync(Organization organization, EventType type)
|
public async Task LogOrganizationEventAsync(Organization organization, EventType type)
|
||||||
{
|
{
|
||||||
var e = new EventMessage
|
var e = new EventMessage(_currentContext)
|
||||||
{
|
{
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
Type = type,
|
Type = type,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Bit.Core.Enums;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -18,7 +19,9 @@ namespace Bit.Core.Utilities
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext httpContext, CurrentContext currentContext)
|
public async Task Invoke(HttpContext httpContext, CurrentContext currentContext)
|
||||||
{
|
{
|
||||||
if(httpContext.User != null)
|
currentContext.HttpContext = httpContext;
|
||||||
|
|
||||||
|
if(httpContext.User != null && httpContext.User.Claims.Any())
|
||||||
{
|
{
|
||||||
var claimsDict = httpContext.User.Claims
|
var claimsDict = httpContext.User.Claims
|
||||||
.GroupBy(c => c.Type)
|
.GroupBy(c => c.Type)
|
||||||
@ -48,7 +51,7 @@ namespace Bit.Core.Utilities
|
|||||||
new CurrentContext.CurrentContentOrganization
|
new CurrentContext.CurrentContentOrganization
|
||||||
{
|
{
|
||||||
Id = new Guid(c.Value),
|
Id = new Guid(c.Value),
|
||||||
Type = Core.Enums.OrganizationUserType.Owner
|
Type = OrganizationUserType.Owner
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +61,7 @@ namespace Bit.Core.Utilities
|
|||||||
new CurrentContext.CurrentContentOrganization
|
new CurrentContext.CurrentContentOrganization
|
||||||
{
|
{
|
||||||
Id = new Guid(c.Value),
|
Id = new Guid(c.Value),
|
||||||
Type = Core.Enums.OrganizationUserType.Admin
|
Type = OrganizationUserType.Admin
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +71,7 @@ namespace Bit.Core.Utilities
|
|||||||
new CurrentContext.CurrentContentOrganization
|
new CurrentContext.CurrentContentOrganization
|
||||||
{
|
{
|
||||||
Id = new Guid(c.Value),
|
Id = new Guid(c.Value),
|
||||||
Type = Core.Enums.OrganizationUserType.User
|
Type = OrganizationUserType.User
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,6 +81,12 @@ namespace Bit.Core.Utilities
|
|||||||
currentContext.DeviceIdentifier = httpContext.Request.Headers["Device-Identifier"];
|
currentContext.DeviceIdentifier = httpContext.Request.Headers["Device-Identifier"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(httpContext.Request.Headers.ContainsKey("Device-Type") &&
|
||||||
|
Enum.TryParse(httpContext.Request.Headers["Device-Type"].ToString(), out DeviceType dType))
|
||||||
|
{
|
||||||
|
currentContext.DeviceType = dType;
|
||||||
|
}
|
||||||
|
|
||||||
await _next.Invoke(httpContext);
|
await _next.Invoke(httpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,9 @@ namespace Bit.Identity
|
|||||||
app.UseMiddleware<CustomIpRateLimitMiddleware>();
|
app.UseMiddleware<CustomIpRateLimitMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add current context
|
||||||
|
app.UseMiddleware<CurrentContextMiddleware>();
|
||||||
|
|
||||||
// Add IdentityServer to the request pipeline.
|
// Add IdentityServer to the request pipeline.
|
||||||
app.UseIdentityServer();
|
app.UseIdentityServer();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
@GroupId UNIQUEIDENTIFIER,
|
@GroupId UNIQUEIDENTIFIER,
|
||||||
@OrganizationUserId UNIQUEIDENTIFIER,
|
@OrganizationUserId UNIQUEIDENTIFIER,
|
||||||
@ActingUserId UNIQUEIDENTIFIER,
|
@ActingUserId UNIQUEIDENTIFIER,
|
||||||
|
@DeviceType SMALLINT,
|
||||||
|
@IpAddress VARCHAR(50),
|
||||||
@Date DATETIME2(7)
|
@Date DATETIME2(7)
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -24,6 +26,8 @@ BEGIN
|
|||||||
[GroupId],
|
[GroupId],
|
||||||
[OrganizationUserId],
|
[OrganizationUserId],
|
||||||
[ActingUserId],
|
[ActingUserId],
|
||||||
|
[DeviceType],
|
||||||
|
[IpAddress],
|
||||||
[Date]
|
[Date]
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
@ -37,6 +41,8 @@ BEGIN
|
|||||||
@GroupId,
|
@GroupId,
|
||||||
@OrganizationUserId,
|
@OrganizationUserId,
|
||||||
@ActingUserId,
|
@ActingUserId,
|
||||||
|
@DeviceType,
|
||||||
|
@IpAddress,
|
||||||
@Date
|
@Date
|
||||||
)
|
)
|
||||||
END
|
END
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
[GroupId] UNIQUEIDENTIFIER NULL,
|
[GroupId] UNIQUEIDENTIFIER NULL,
|
||||||
[OrganizationUserId] UNIQUEIDENTIFIER NULL,
|
[OrganizationUserId] UNIQUEIDENTIFIER NULL,
|
||||||
[ActingUserId] UNIQUEIDENTIFIER NULL,
|
[ActingUserId] UNIQUEIDENTIFIER NULL,
|
||||||
|
[DeviceType] SMALLINT NULL,
|
||||||
|
[IpAddress] VARCHAR(50) NULL,
|
||||||
[Date] DATETIME2 (7) NOT NULL,
|
[Date] DATETIME2 (7) NOT NULL,
|
||||||
CONSTRAINT [PK_Event] PRIMARY KEY CLUSTERED ([Id] ASC)
|
CONSTRAINT [PK_Event] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||||
);
|
);
|
||||||
@ -15,5 +17,5 @@
|
|||||||
|
|
||||||
GO
|
GO
|
||||||
CREATE NONCLUSTERED INDEX [IX_Event_DateOrganizationIdUserId]
|
CREATE NONCLUSTERED INDEX [IX_Event_DateOrganizationIdUserId]
|
||||||
ON [dbo].[Event]([Date] ASC, [OrganizationId] ASC, [UserId] ASC);
|
ON [dbo].[Event]([Date] ASC, [OrganizationId] ASC, [UserId] ASC, [CipherId] ASC);
|
||||||
|
|
||||||
|
@ -259,12 +259,14 @@ BEGIN
|
|||||||
[GroupId] UNIQUEIDENTIFIER NULL,
|
[GroupId] UNIQUEIDENTIFIER NULL,
|
||||||
[OrganizationUserId] UNIQUEIDENTIFIER NULL,
|
[OrganizationUserId] UNIQUEIDENTIFIER NULL,
|
||||||
[ActingUserId] UNIQUEIDENTIFIER NULL,
|
[ActingUserId] UNIQUEIDENTIFIER NULL,
|
||||||
|
[DeviceType] SMALLINT NULL,
|
||||||
|
[IpAddress] VARCHAR(50) NULL,
|
||||||
[Date] DATETIME2 (7) NOT NULL,
|
[Date] DATETIME2 (7) NOT NULL,
|
||||||
CONSTRAINT [PK_Event] PRIMARY KEY CLUSTERED ([Id] ASC)
|
CONSTRAINT [PK_Event] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE NONCLUSTERED INDEX [IX_Event_DateOrganizationIdUserId]
|
CREATE NONCLUSTERED INDEX [IX_Event_DateOrganizationIdUserId]
|
||||||
ON [dbo].[Event]([Date] ASC, [OrganizationId] ASC, [UserId] ASC);
|
ON [dbo].[Event]([Date] ASC, [OrganizationId] ASC, [UserId] ASC, [CipherId] ASC);
|
||||||
END
|
END
|
||||||
GO
|
GO
|
||||||
|
|
||||||
@ -284,6 +286,8 @@ CREATE PROCEDURE [dbo].[Event_Create]
|
|||||||
@GroupId UNIQUEIDENTIFIER,
|
@GroupId UNIQUEIDENTIFIER,
|
||||||
@OrganizationUserId UNIQUEIDENTIFIER,
|
@OrganizationUserId UNIQUEIDENTIFIER,
|
||||||
@ActingUserId UNIQUEIDENTIFIER,
|
@ActingUserId UNIQUEIDENTIFIER,
|
||||||
|
@DeviceType SMALLINT,
|
||||||
|
@IpAddress VARCHAR(50),
|
||||||
@Date DATETIME2(7)
|
@Date DATETIME2(7)
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -300,6 +304,8 @@ BEGIN
|
|||||||
[GroupId],
|
[GroupId],
|
||||||
[OrganizationUserId],
|
[OrganizationUserId],
|
||||||
[ActingUserId],
|
[ActingUserId],
|
||||||
|
[DeviceType],
|
||||||
|
[IpAddress],
|
||||||
[Date]
|
[Date]
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
@ -313,6 +319,8 @@ BEGIN
|
|||||||
@GroupId,
|
@GroupId,
|
||||||
@OrganizationUserId,
|
@OrganizationUserId,
|
||||||
@ActingUserId,
|
@ActingUserId,
|
||||||
|
@DeviceType,
|
||||||
|
@IpAddress,
|
||||||
@Date
|
@Date
|
||||||
)
|
)
|
||||||
END
|
END
|
||||||
|
Loading…
Reference in New Issue
Block a user