public override Task <IDisplayResult> DisplayAsync(AuditTrailEvent auditTrailEvent, AuditTrailUserEvent userEvent, BuildDisplayContext context) { return(Task.FromResult <IDisplayResult>( Initialize <AuditTrailUserEventDetailViewModel>("AuditTrailUserEventDetail_DetailAdmin", m => BuildViewModel(m, auditTrailEvent, userEvent)) .Location("DetailAdmin", "Content:10") )); }
private static void BuildViewModel(AuditTrailUserEventViewModel m, AuditTrailEvent auditTrailEvent, AuditTrailUserEvent userEvent) { m.AuditTrailEvent = auditTrailEvent; m.Name = userEvent.Name; m.UserId = userEvent.UserId; m.UserName = userEvent.UserName; }
private async Task <IShape> BuildEventShapeAsync(string shapeType, AuditTrailEvent auditTrailEvent, string displayType) { dynamic auditTrailEventActionsShape = await _shapeFactory.CreateAsync(shapeType, Arguments.From(new Dictionary <string, object> { { "AuditTrailEvent", auditTrailEvent }, { "Descriptor", _auditTrailManager.DescribeEvent(auditTrailEvent) }, { "EventData", auditTrailEvent.Get(auditTrailEvent.EventName) } })); if (auditTrailEvent.Category == "Content") { var contentItem = auditTrailEvent.Get(auditTrailEvent.EventName).ToObject <ContentItem>(); var availableVersionsCount = await _session.Query <ContentItem, ContentItemIndex>() .Where(index => index.ContentItemId == contentItem.ContentItemId).CountAsync(); auditTrailEventActionsShape.AvailableVersionsCount = availableVersionsCount; } var metaData = auditTrailEventActionsShape.Metadata; metaData.DisplayType = displayType; metaData.Alternates.Add($"{shapeType}_{displayType}"); metaData.Alternates.Add($"{shapeType}__{auditTrailEvent.Category}"); metaData.Alternates.Add($"{shapeType}_{displayType}__{auditTrailEvent.Category}"); metaData.Alternates.Add($"{shapeType}__{auditTrailEvent.Category}__{auditTrailEvent.EventName}"); metaData.Alternates.Add($"{shapeType}_{displayType}__{auditTrailEvent.Category}__{auditTrailEvent.EventName}"); return(auditTrailEventActionsShape); }
public static AuditTrailEventDescriptor Default(AuditTrailEvent auditTrailEvent) => new AuditTrailEventDescriptor( auditTrailEvent.Name, auditTrailEvent.Category, (sp) => new LocalizedString(auditTrailEvent.Name, auditTrailEvent.Name), (sp) => new LocalizedString(auditTrailEvent.Category, auditTrailEvent.Category), (sp) => new LocalizedString(auditTrailEvent.Name, auditTrailEvent.Name) );
public async Task <IShape> BuildAdditionalColumnsShapesAsync(AuditTrailEvent auditTrailEvent) { var additionalColumnDisplay = await _shapeFactory.CreateAsync("AuditTrailEventAdditionalColumn"); _auditTrailEventHandlers.Invoke((handler, display) => handler.DisplayAdditionalColumnsAsync(display), new DisplayAdditionalColumnsContext(auditTrailEvent, additionalColumnDisplay as Shape), Logger); return(additionalColumnDisplay); }
private static void BuildSummaryViewModel(AuditTrailContentEventViewModel m, AuditTrailEvent model, AuditTrailContentEvent contentEvent, AuditTrailEventDescriptor descriptor, string latestVersionId) { m.AuditTrailEvent = model; m.Descriptor = descriptor; m.Name = contentEvent.Name; m.ContentItem = contentEvent.ContentItem; m.VersionNumber = contentEvent.VersionNumber; m.Comment = contentEvent.Comment; m.LatestVersionId = latestVersionId; m.ContentEvent = contentEvent; }
/// <summary> /// Returns a basic descriptor based on an event record. /// This is useful in cases where event records were previously stored by providers that are no longer enabled. /// </summary> public static AuditTrailEventDescriptor Basic(AuditTrailEvent auditTrailEvent) => new AuditTrailEventDescriptor { LocalizedName = new LocalizedString(auditTrailEvent.EventName, auditTrailEvent.EventName), FullEventName = auditTrailEvent.FullEventName, EventName = auditTrailEvent.EventName, CategoryDescriptor = new AuditTrailCategoryDescriptor { Category = auditTrailEvent.Category, Events = Enumerable.Empty <AuditTrailEventDescriptor>(), LocalizedName = new LocalizedString(auditTrailEvent.Category, auditTrailEvent.Category) } };
private void BuildAuditTrailEvent(AuditTrailEvent auditTrailEvent, Dictionary <string, object> eventData) { var contentItem = eventData.Get <ContentItem>("ContentItem"); auditTrailEvent.Put(auditTrailEvent.EventName, contentItem); auditTrailEvent.Put(new ContentEvent { ContentItemId = contentItem.ContentItemId, ContentType = contentItem.ContentType, VersionNumber = eventData.Get <int>("VersionNumber"), EventName = auditTrailEvent.EventName, Published = contentItem.IsPublished() }); }
public async Task RecordEventAsync <TEvent>(AuditTrailContext <TEvent> context) where TEvent : class, new() { if (_shellSettings.State == TenantState.Initializing && String.IsNullOrEmpty(context.UserName)) { var feature = _httpContextAccessor.HttpContext.Features.Get <RecipeEnvironmentFeature>(); if (feature != null && feature.Properties.TryGetValue(SetupConstants.AdminUsername, out var adminUsername)) { context.UserName = (string)adminUsername; } } var descriptor = DescribeEvent(context.Name, context.Category); if (descriptor == null || !await IsEventEnabledAsync(descriptor)) { return; } var createContext = new AuditTrailCreateContext <TEvent>( context.Name, context.Category, context.CorrelationId, context.UserId, context.UserName, context.AuditTrailEventItem ); await _auditTrailEventHandlers.InvokeAsync((handler, context) => handler.CreateAsync(context), createContext, _logger); var auditTrailEvent = new AuditTrailEvent { EventId = _auditTrailIdGenerator.GenerateUniqueId(), Category = createContext.Category, Name = createContext.Name, CorrelationId = createContext.CorrelationId, UserId = createContext.UserId, UserName = createContext.UserName ?? "", NormalizedUserName = String.IsNullOrEmpty(createContext.UserName) ? "" : _keyNormalizer.NormalizeName(createContext.UserName), ClientIpAddress = String.IsNullOrEmpty(createContext.ClientIpAddress) ? await GetClientIpAddressAsync() : createContext.ClientIpAddress, CreatedUtc = createContext.CreatedUtc ?? _clock.UtcNow }; auditTrailEvent.Put(createContext.AuditTrailEventItem); await _auditTrailEventHandlers.InvokeAsync((handler, context, auditTrailEvent) => handler.AlterAsync(context, auditTrailEvent), createContext, auditTrailEvent, _logger); _session.Save(auditTrailEvent, AuditTrailEvent.Collection); }
public async Task AddAuditTrailEventAsync <TAuditTrailEventProvider>(AuditTrailContext auditTrailContext) where TAuditTrailEventProvider : IAuditTrailEventProvider { var eventDescriptors = DescribeEvents(auditTrailContext.EventName, typeof(TAuditTrailEventProvider).FullName); foreach (var eventDescriptor in eventDescriptors) { if (!await IsEventEnabledAsync(eventDescriptor)) { return; } var auditTrailCreateContext = new AuditTrailCreateContext( auditTrailContext.EventName, auditTrailContext.UserName, auditTrailContext.EventData, auditTrailContext.EventFilterKey, auditTrailContext.EventFilterData); _auditTrailEventHandlers.Invoke((handler, context) => handler.CreateAsync(context), auditTrailCreateContext, Logger); var auditTrailEvent = new AuditTrailEvent { Id = _iidGenerator.GenerateUniqueId(), Category = eventDescriptor.CategoryDescriptor.Category, EventName = auditTrailCreateContext.EventName, FullEventName = eventDescriptor.FullEventName, UserName = !string.IsNullOrEmpty(auditTrailCreateContext.UserName) ? auditTrailContext.UserName : T["[empty]"], CreatedUtc = auditTrailCreateContext.CreatedUtc ?? _clock.UtcNow, Comment = auditTrailCreateContext.Comment.NewlinesToHtml(), EventFilterData = auditTrailCreateContext.EventFilterData, EventFilterKey = auditTrailCreateContext.EventFilterKey, ClientIpAddress = string.IsNullOrEmpty(auditTrailCreateContext.ClientIpAddress) ? await GetClientAddressAsync() : auditTrailCreateContext.ClientIpAddress }; eventDescriptor.BuildAuditTrailEvent(auditTrailEvent, auditTrailCreateContext.EventData); _session.Save(auditTrailEvent); } }
public DisplayAdditionalColumnsContext(AuditTrailEvent auditTrailEvent, Shape display) { AuditTrailEvent = auditTrailEvent; Display = display; }
public async Task <IShape> BuildActionsAsync(AuditTrailEvent auditTrailEvent, string displayType) => await BuildEventShapeAsync("AuditTrailEventActions", auditTrailEvent, displayType);
private void BuildAuditTrailEvent(AuditTrailEvent auditTrailEvent, Dictionary <string, object> eventData) => auditTrailEvent.Put(auditTrailEvent.EventName, eventData);
public AuditTrailEventDescriptor DescribeEvent(AuditTrailEvent auditTrailEvent) => DescribeCategories().SelectMany( categoryDescriptor => categoryDescriptor.Events.Where( eventDescriptor => eventDescriptor.FullEventName == auditTrailEvent.FullEventName)).FirstOrDefault();
public override bool CanHandleModel(AuditTrailEvent auditTrailEvent) => auditTrailEvent.Properties.ContainsKey(PropertyName);
public override async Task <IDisplayResult> DisplayAsync(AuditTrailEvent auditTrailEvent, AuditTrailContentEvent contentEvent, BuildDisplayContext context) { var contentItemId = contentEvent.ContentItem.ContentItemId; if (!_latestVersionId.TryGetValue(contentItemId, out var latestVersionId)) { latestVersionId = (await _session.QueryIndex <ContentItemIndex>(index => index.ContentItemId == contentItemId && index.Latest) .FirstOrDefaultAsync()) ?.ContentItemVersionId; _latestVersionId[contentItemId] = latestVersionId; } var descriptor = _auditTrailManager.DescribeEvent(auditTrailEvent); return(Combine( Initialize <AuditTrailContentEventViewModel>("AuditTrailContentEventData_SummaryAdmin", m => BuildSummaryViewModel(m, auditTrailEvent, contentEvent, descriptor, latestVersionId)) .Location("SummaryAdmin", "EventData:10"), Initialize <AuditTrailContentEventViewModel>("AuditTrailContentEventContent_SummaryAdmin", m => BuildSummaryViewModel(m, auditTrailEvent, contentEvent, descriptor, latestVersionId)) .Location("SummaryAdmin", "Content:10"), Initialize <AuditTrailContentEventViewModel>("AuditTrailContentEventActions_SummaryAdmin", m => BuildSummaryViewModel(m, auditTrailEvent, contentEvent, descriptor, latestVersionId)) .Location("SummaryAdmin", "Actions:5"), Initialize <AuditTrailContentEventDetailViewModel>("AuditTrailContentEventDetail_DetailAdmin", async m => { BuildSummaryViewModel(m, auditTrailEvent, contentEvent, descriptor, latestVersionId); var previousContentItem = (await _session.Query <AuditTrailEvent, AuditTrailEventIndex>(collection: AuditTrailEvent.Collection) .Where(index => index.Category == "Content" && index.CreatedUtc <= auditTrailEvent.CreatedUtc && index.EventId != auditTrailEvent.EventId && index.CorrelationId == contentEvent.ContentItem.ContentItemId) .OrderByDescending(index => index.Id) .FirstOrDefaultAsync())? .As <AuditTrailContentEvent>() .ContentItem; if (previousContentItem != null) { var current = JObject.FromObject(contentEvent.ContentItem); var previous = JObject.FromObject(previousContentItem); previous.Remove(nameof(AuditTrailPart)); current.Remove(nameof(AuditTrailPart)); m.PreviousContentItem = previousContentItem; m.Previous = previous.ToString(); m.Current = current.ToString(); } }).Location("DetailAdmin", "Content:5"), Initialize <AuditTrailContentEventDetailViewModel>("AuditTrailContentEventDiff_DetailAdmin", async m => { BuildSummaryViewModel(m, auditTrailEvent, contentEvent, descriptor, latestVersionId); var previousContentItem = (await _session.Query <AuditTrailEvent, AuditTrailEventIndex>(collection: AuditTrailEvent.Collection) .Where(index => index.Category == "Content" && index.CreatedUtc <= auditTrailEvent.CreatedUtc && index.EventId != auditTrailEvent.EventId && index.CorrelationId == contentEvent.ContentItem.ContentItemId) .OrderByDescending(index => index.Id) .FirstOrDefaultAsync())? .As <AuditTrailContentEvent>() .ContentItem; if (previousContentItem != null) { var current = JObject.FromObject(contentEvent.ContentItem); var previous = JObject.FromObject(previousContentItem); previous.Remove(nameof(AuditTrailPart)); current.Remove(nameof(AuditTrailPart)); m.PreviousContentItem = previousContentItem; m.Previous = previous.ToString(); m.Current = current.ToString(); } }).Location("DetailAdmin", "Content:5#Diff") )); }
public void Discover(ShapeTableBuilder builder) { builder.Describe("AuditTrailEvent").OnDisplaying(async context => { dynamic shape = context.Shape; var auditTrailEvent = (AuditTrailEvent)shape.AuditTrailEvent; if (auditTrailEvent.Category != "Content") { return; } var contentItemJToken = auditTrailEvent.Get(auditTrailEvent.EventName); var contentEventJToken = auditTrailEvent.Get(nameof(ContentEvent)); var contentItem = contentItemJToken.ToObject <ContentItem>(); if (context.Shape.Metadata.DisplayType == "Detail") { var session = context.ServiceProvider.GetRequiredService <IYesSqlSession>(); AuditTrailEvent previousAuditTrailEvent = null; previousAuditTrailEvent = await session.Query <AuditTrailEvent, AuditTrailEventIndex>() .Where(eventIndex => eventIndex.CreatedUtc < auditTrailEvent.CreatedUtc && eventIndex.Category == "Content" && eventIndex.EventFilterData == contentItem.ContentItemId) .OrderByDescending(eventIndex => eventIndex.CreatedUtc) .FirstOrDefaultAsync(); if (previousAuditTrailEvent != null) { var contentDefinitionManager = context.ServiceProvider.GetRequiredService <IContentDefinitionManager>(); var previousContentItemJToken = previousAuditTrailEvent.Get(previousAuditTrailEvent.EventName); var previousContentItem = previousContentItemJToken.ToObject <ContentItem>(); var currentTypeDefinition = contentDefinitionManager.LoadTypeDefinition(contentItem.ContentType); var previousTypeDefinition = contentDefinitionManager.LoadTypeDefinition(previousContentItem.ContentType); var contentParts = currentTypeDefinition.Parts .Select(typePartDefinition => typePartDefinition.Name) .Intersect(previousTypeDefinition.Parts.Select(b => b.Name)); JObject diff = JsonExtensions.FindDiff(contentItem.Content, previousContentItem.Content); var diffNodes = new List <DiffNode>(); foreach (var contentPart in contentParts) { if (diff.ContainsKey(contentPart)) { foreach (var diffNode in JsonExtensions.GenerateDiffNodes(diff[contentPart])) { diffNode.Context = contentItem.ContentType + "/" + diffNode.Context; diffNodes.Add(diffNode); } } } diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.Author))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.ContentItemVersionId))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.CreatedUtc))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.DisplayText))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.Latest))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.Owner))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.ModifiedUtc))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.Published))); diffNodes.AddToListIfNotNull( contentItem.LogPropertyChange(previousContentItem, nameof(contentItem.PublishedUtc))); shape.DiffNodes = diffNodes; } } shape.ContentItem = contentItem; shape.VersionNumber = contentEventJToken.Value <int>(nameof(ContentEvent.VersionNumber)); }); builder.Describe("AuditTrailEventActions").OnDisplaying(context => { dynamic shape = context.Shape; var auditTrailEvent = (AuditTrailEvent)shape.AuditTrailEvent; if (auditTrailEvent.Category != "Content") { return; } var contentItem = auditTrailEvent.Get(auditTrailEvent.EventName).ToObject <ContentItem>(); var contentEventJToken = auditTrailEvent.Get(nameof(ContentEvent)); shape.ContentItem = contentItem; shape.VersionNumber = contentEventJToken.Value <int>(nameof(ContentEvent.VersionNumber)); }); }
public virtual Task AlterAsync(AuditTrailCreateContext context, AuditTrailEvent auditTrailEvent) => Task.CompletedTask;
public AuditTrailEventDescriptor DescribeEvent(AuditTrailEvent auditTrailEvent) => DescribeEvent(auditTrailEvent.Name, auditTrailEvent.Category) ?? AuditTrailEventDescriptor.Default(auditTrailEvent);