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;
 }
예제 #3
0
        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);
        }
예제 #4
0
 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)
     );
예제 #5
0
        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);
        }
예제 #6
0
 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()
            });
        }
예제 #9
0
        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;
 }
예제 #12
0
 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();
예제 #15
0
 public override bool CanHandleModel(AuditTrailEvent auditTrailEvent)
 => auditTrailEvent.Properties.ContainsKey(PropertyName);
예제 #16
0
        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));
            });
        }
예제 #18
0
 public virtual Task AlterAsync(AuditTrailCreateContext context, AuditTrailEvent auditTrailEvent) => Task.CompletedTask;
예제 #19
0
 public AuditTrailEventDescriptor DescribeEvent(AuditTrailEvent auditTrailEvent) =>
 DescribeEvent(auditTrailEvent.Name, auditTrailEvent.Category)
 ?? AuditTrailEventDescriptor.Default(auditTrailEvent);