Implementing a ContentType/Part audit trail event provider.

This commit is contained in:
sfmskywalker
2014-05-27 18:32:04 +02:00
parent 6bb121edf6
commit 3fe5242dfd
19 changed files with 339 additions and 1 deletions

View File

@@ -10,4 +10,4 @@ Features:
Name: AuditTrail
Description: Provides the core audit trail framework.
Category: Security
Dependencies: Orchard.Users, Orchard.Roles
Dependencies: Orchard.Users, Orchard.Roles, Orchard.ContentTypes

View File

@@ -91,6 +91,18 @@
<Content Include="Views\AuditTrailEvent-Role-RoleCreated.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-Role-PermissionAdded.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-Role-PermissionRemoved.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-Created.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-Removed.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-TypeSettingsUpdated.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-PartAdded.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-PartRemoved.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-Created.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-Removed.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-PartSettingsUpdated.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-FieldAdded.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-FieldRemoved.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentType-PartSettingsUpdated.SummaryAdmin.cshtml" />
<Content Include="Views\AuditTrailEvent-ContentPart-FieldSettingsUpdated.SummaryAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
@@ -106,6 +118,11 @@
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Drivers\ContentsDriver.cs" />
<Compile Include="Providers\ContentDefinition\ContentDefinitionEventHandler.cs" />
<Compile Include="Providers\ContentDefinition\GlobalContentDefinitionEditorEvents.cs" />
<Compile Include="Providers\ContentDefinition\ContentPartAuditTrailEventProvider.cs" />
<Compile Include="Providers\ContentDefinition\ContentTypeAuditTrailEventProvider.cs" />
<Compile Include="Providers\ContentDefinition\IContentDefinitionEventHandler.cs" />
<Compile Include="Providers\Content\AuditTrailEventHandler.cs" />
<Compile Include="Helpers\EventDataHelper.cs" />
<Compile Include="Models\AuditTrailFilterParameters.cs" />

View File

@@ -0,0 +1,80 @@
using System.Collections.Generic;
using Orchard.AuditTrail.Services;
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.AuditTrail.Providers.ContentDefinition {
public class ContentDefinitionEventHandler : IContentDefinitionEventHandler {
private readonly IAuditTrailManager _auditTrailManager;
private readonly IWorkContextAccessor _wca;
public ContentDefinitionEventHandler(IAuditTrailManager auditTrailManager, IWorkContextAccessor wca) {
_auditTrailManager = auditTrailManager;
_wca = wca;
}
public void ContentTypeCreated(dynamic context) {
RecordContentTypeAuditTrail(ContentTypeAuditTrailEventProvider.Created, context.ContentTypeDefinition);
}
public void ContentTypeRemoved(dynamic context) {
RecordContentTypeAuditTrail(ContentTypeAuditTrailEventProvider.Removed, context.ContentTypeDefinition);
}
public void ContentPartCreated(dynamic context) {
RecordContentPartAuditTrail(ContentPartAuditTrailEventProvider.Created, context.ContentPartDefinition);
}
public void ContentPartRemoved(dynamic context) {
RecordContentPartAuditTrail(ContentPartAuditTrailEventProvider.Removed, context.ContentPartDefinition);
}
public void ContentPartAttached(dynamic context) {
RecordContentTypePartAuditTrail(ContentTypeAuditTrailEventProvider.PartAdded, context.ContentTypeName, context.ContentPartName);
}
public void ContentPartDetached(dynamic context) {
RecordContentTypePartAuditTrail(ContentTypeAuditTrailEventProvider.PartRemoved, context.ContentTypeName, context.ContentPartName);
}
public void ContentFieldAttached(dynamic context) {
var eventData = new Dictionary<string, object> {
{"ContentPartName", context.ContentPartName},
{"ContentFieldName", context.ContentFieldName},
{"ContentFieldTypeName", context.ContentFieldTypeName},
{"ContentFieldDisplayName", context.ContentFieldDisplayName}
};
_auditTrailManager.Record<ContentPartAuditTrailEventProvider>(ContentPartAuditTrailEventProvider.FieldAdded, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contentpart", eventFilterData: context.ContentPartName);
}
public void ContentFieldDetached(dynamic context) {
var eventData = new Dictionary<string, object> {
{"ContentPartName", context.ContentPartName},
{"ContentFieldName", context.ContentFieldName}
};
_auditTrailManager.Record<ContentPartAuditTrailEventProvider>(ContentPartAuditTrailEventProvider.FieldRemoved, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contentpart", eventFilterData: context.ContentPartName);
}
private void RecordContentTypeAuditTrail(string eventName, ContentTypeDefinition contentTypeDefinition) {
var eventData = new Dictionary<string, object> {
{"ContentTypeName", contentTypeDefinition.Name},
{"ContentTypeDisplayName", contentTypeDefinition.DisplayName},
};
_auditTrailManager.Record<ContentTypeAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contenttype", eventFilterData: contentTypeDefinition.Name);
}
private void RecordContentPartAuditTrail(string eventName, ContentPartDefinition contentPartDefinition) {
var eventData = new Dictionary<string, object> {
{"ContentPartName", contentPartDefinition.Name}
};
_auditTrailManager.Record<ContentPartAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contentpart", eventFilterData: contentPartDefinition.Name);
}
private void RecordContentTypePartAuditTrail(string eventName, string contentTypeName, string contentPartName) {
var eventData = new Dictionary<string, object> {
{"ContentTypeName", contentTypeName},
{"ContentPartName", contentPartName}
};
_auditTrailManager.Record<ContentTypeAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contenttype", eventFilterData: contentTypeName);
}
}
}

View File

@@ -0,0 +1,25 @@
using Orchard.AuditTrail.Models;
using Orchard.AuditTrail.Services;
namespace Orchard.AuditTrail.Providers.ContentDefinition {
public class ContentPartAuditTrailEventProvider : AuditTrailEventProviderBase {
public const string Created = "Created";
public const string Removed = "Removed";
public const string DescriptionChanged = "DescriptionChanged";
public const string FieldAdded = "FieldAdded";
public const string FieldRemoved = "FieldRemoved";
public const string PartSettingsUpdated = "PartSettingsUpdated";
public const string FieldSettingsUpdated = "FieldSettingsUpdated";
public override void Describe(DescribeContext context) {
context.For("ContentPart", T("Content Part"))
.Event(this, Created, T("Created"), T("Content Type was created."), enableByDefault: true)
.Event(this, Removed, T("Removed"), T("Content Type was removed."), enableByDefault: true)
.Event(this, DescriptionChanged, T("Description changed"), T("Content Part description was changed."), enableByDefault: true)
.Event(this, FieldAdded, T("Field added"), T("Content Field was added."), enableByDefault: true)
.Event(this, FieldRemoved, T("Field removed"), T("Content Field was removed."), enableByDefault: true)
.Event(this, PartSettingsUpdated, T("Part settings updated"), T("Content Part settings were updated."), enableByDefault: true)
.Event(this, FieldSettingsUpdated, T("Field settings updated"), T("Content Field settings were updated."), enableByDefault: true);
}
}
}

View File

@@ -0,0 +1,23 @@
using Orchard.AuditTrail.Models;
using Orchard.AuditTrail.Services;
namespace Orchard.AuditTrail.Providers.ContentDefinition {
public class ContentTypeAuditTrailEventProvider : AuditTrailEventProviderBase {
public const string Created = "Created";
public const string Removed = "Removed";
public const string PartAdded = "PartAdded";
public const string PartRemoved = "PartRemoved";
public const string TypeSettingsUpdated = "TypeSettingsUpdated";
public const string PartSettingsUpdated = "PartSettingsUpdated";
public override void Describe(DescribeContext context) {
context.For("ContentType", T("Content Type"))
.Event(this, Created, T("Created"), T("Content Type was created."), enableByDefault: true)
.Event(this, Removed, T("Removed"), T("Content Type was removed."), enableByDefault: true)
.Event(this, PartAdded, T("Part added"), T("Content Part was added."), enableByDefault: true)
.Event(this, PartRemoved, T("Part removed"), T("Content Part was removed."), enableByDefault: true)
.Event(this, TypeSettingsUpdated, T("Type Settings updated"), T("Content Type settings were updated."), enableByDefault: true)
.Event(this, PartSettingsUpdated, T("Part Settings updated"), T("Content Part settings were updated."), enableByDefault: true);
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using Orchard.AuditTrail.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.AuditTrail.Providers.ContentDefinition {
public class GlobalContentDefinitionEditorEvents : ContentDefinitionEditorEventsBase {
private readonly IAuditTrailManager _auditTrailManager;
private readonly IWorkContextAccessor _wca;
public GlobalContentDefinitionEditorEvents(IAuditTrailManager auditTrailManager, IWorkContextAccessor wca) {
_auditTrailManager = auditTrailManager;
_wca = wca;
}
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
var eventData = new Dictionary<string, object> {
{"ContentTypeName", builder.Name}
};
RecordContentTypeAuditTrail(ContentTypeAuditTrailEventProvider.TypeSettingsUpdated, eventData, builder.Name);
yield break;
}
public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel) {
var eventData = new Dictionary<string, object> {
{"ContentPartName", builder.Name},
{"ContentTypeName", builder.TypeName}
};
RecordContentTypeAuditTrail(ContentTypeAuditTrailEventProvider.PartSettingsUpdated, eventData, builder.TypeName);
yield break;
}
public override IEnumerable<TemplateViewModel> PartEditorUpdate(ContentPartDefinitionBuilder builder, IUpdateModel updateModel) {
var eventData = new Dictionary<string, object> {
{"ContentPartName", builder.Name}
};
RecordContentPartAuditTrail(ContentPartAuditTrailEventProvider.PartSettingsUpdated, eventData, builder.Name);
yield break;
}
public override IEnumerable<TemplateViewModel> PartFieldEditorUpdate(ContentPartFieldDefinitionBuilder builder, IUpdateModel updateModel) {
var eventData = new Dictionary<string, object> {
{"ContentFieldName", builder.Name},
{"ContentFieldType", builder.FieldType},
{"ContentPartName", builder.PartName}
};
RecordContentPartAuditTrail(ContentPartAuditTrailEventProvider.FieldSettingsUpdated, eventData, builder.PartName);
yield break;
}
private void RecordContentTypeAuditTrail(string eventName, IDictionary<string, object> eventData, string contentTypeName) {
_auditTrailManager.Record<ContentTypeAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contenttype", eventFilterData: contentTypeName);
}
private void RecordContentPartAuditTrail(string eventName, IDictionary<string, object> eventData, string contentPartName) {
_auditTrailManager.Record<ContentPartAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties: null, eventData: eventData, eventFilterKey: "contentpart", eventFilterData: contentPartName);
}
}
}

View File

@@ -0,0 +1,14 @@
using Orchard.Events;
namespace Orchard.AuditTrail.Providers.ContentDefinition {
public interface IContentDefinitionEventHandler : IEventHandler {
void ContentTypeCreated(dynamic context);
void ContentTypeRemoved(dynamic context);
void ContentPartCreated(dynamic context);
void ContentPartRemoved(dynamic context);
void ContentPartAttached(dynamic context);
void ContentPartDetached(dynamic context);
void ContentFieldAttached(dynamic context);
void ContentFieldDetached(dynamic context);
}
}

View File

@@ -0,0 +1,9 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-part">
@T("Created the <strong>{0}</strong> content part.", contentPartName)
</section>

View File

@@ -0,0 +1,12 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
var contentFieldName = eventData.Get<string>("ContentFieldName");
var contentFieldTypeName = eventData.Get<string>("ContentFieldTypeName");
var contentDisplayName = eventData.Get<string>("ContentDisplayName");
}
<section class="event-content-part">
@T("Added the <strong>{0}</strong> content field of type <strong>{1}</strong> to the <strong>{2}</strong> content part.", contentFieldName, contentFieldTypeName, contentPartName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
var contentFieldName = eventData.Get<string>("ContentFieldName");
}
<section class="event-content-part">
@T("Removed the <strong>{0}</strong> content field from the <strong>{1}</strong> content part.", contentFieldName, contentPartName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
var contentFieldName = eventData.Get<string>("ContentFieldName");
}
<section class="event-content-part">
@T("Settings for the <strong>{0}</strong> content field of the <strong>{1}</strong> content part were updated.", contentFieldName, contentPartName)
</section>

View File

@@ -0,0 +1,9 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-part">
@T("Settings for the <strong>{0}</strong> content part were updated.", contentPartName)
</section>

View File

@@ -0,0 +1,9 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-part">
@T("Removed the <strong>{0}</strong> content part.", contentPartName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
var contentTypeDisplayName = eventData.Get<string>("ContentTypeDisplayName");
}
<section class="event-content-type">
@T("Created the <strong>{0}</strong> content type.", contentTypeName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-type">
@T("Added the <strong>{0}</strong> content part to the <strong>{1}</strong> content type.", contentPartName, contentTypeName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-type">
@T("Removed the <strong>{0}</strong> content part from the <strong>{1}</strong> content type.", contentPartName, contentTypeName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
var contentPartName = eventData.Get<string>("ContentPartName");
}
<section class="event-content-type">
@T("Settings for the <strong>{0}</strong> content part attached to the <strong>{1}</strong> content type were updated.", contentPartName, contentTypeName)
</section>

View File

@@ -0,0 +1,10 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
var contentTypeDisplayName = eventData.Get<string>("ContentTypeDisplayName");
}
<section class="event-content-type">
@T("Removed the <strong>{0}</strong> content type.", contentTypeName)
</section>

View File

@@ -0,0 +1,9 @@
@using Orchard.AuditTrail.Helpers
@{
var eventData = (IDictionary<string, object>) Model.EventData;
var contentTypeName = eventData.Get<string>("ContentTypeName");
}
<section class="event-content-type">
@T("Settings for the <strong>{0}</strong> content type were updated.", contentTypeName)
</section>