mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Implementing audit trail site settings.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
|
||||
namespace Orchard.AuditTrail.Drivers {
|
||||
public class AuditTrailSiteSettingsPartDriver : ContentPartDriver<AuditTrailSiteSettingsPart> {
|
||||
private readonly IAuditTrailManager _auditTrailManager;
|
||||
|
||||
public AuditTrailSiteSettingsPartDriver(IAuditTrailManager auditTrailManager) {
|
||||
_auditTrailManager = auditTrailManager;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(AuditTrailSiteSettingsPart part, dynamic shapeHelper) {
|
||||
return Editor(part, null, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(AuditTrailSiteSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_AuditTrailSiteSettings_Edit", () => {
|
||||
var descriptors = _auditTrailManager.Describe();
|
||||
var eventSettings = part.EventSettings.ToList();
|
||||
var viewModel = new AuditTrailSiteSettingsViewModel {
|
||||
AutoTrim = part.AutoTrim,
|
||||
AutoTrimThreshold = part.AutoTrimThreshold,
|
||||
Categories = (from categoryDescriptor in descriptors
|
||||
select new AuditTrailCategorySettingsViewModel {
|
||||
Category = categoryDescriptor.Category,
|
||||
Name = categoryDescriptor.Name,
|
||||
Events = (from eventDescriptor in categoryDescriptor.Events
|
||||
let eventSetting = eventSettings.FirstOrDefault(x => x.EventName == eventDescriptor.Event)
|
||||
select new AuditTrailEventSettingsViewModel {
|
||||
Event = eventDescriptor.Event,
|
||||
Name = eventDescriptor.Name,
|
||||
Description = eventDescriptor.Description,
|
||||
IsEnabled = eventSetting != null ? eventSetting.IsEnabled : eventDescriptor.IsEnabledByDefault
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||
foreach (var eventSettingViewModel in viewModel.Categories.SelectMany(x => x.Events)) {
|
||||
var eventSetting = eventSettings.FirstOrDefault(x => x.EventName == eventSettingViewModel.Event);
|
||||
|
||||
if (eventSetting == null) {
|
||||
eventSetting = new AuditTrailEventSetting { EventName = eventSettingViewModel.Event};
|
||||
eventSettings.Add(eventSetting);
|
||||
}
|
||||
|
||||
eventSetting.IsEnabled = eventSettingViewModel.IsEnabled;
|
||||
}
|
||||
part.EventSettings = eventSettings;
|
||||
part.AutoTrim = viewModel.AutoTrim;
|
||||
part.AutoTrimThreshold = viewModel.AutoTrimThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.AuditTrailSiteSettings", Model: viewModel, Prefix: Prefix);
|
||||
}).OnGroup("Audit Trail");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.AuditTrail.Handlers {
|
||||
public class AuditTrailSiteSettingsPartHandler : ContentHandler {
|
||||
public AuditTrailSiteSettingsPartHandler() {
|
||||
OnActivated<AuditTrailSiteSettingsPart>(SetupLazyFields);
|
||||
OnGetContentItemMetadata<AuditTrailSiteSettingsPart>(GetMetadata);
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
private void GetMetadata(GetContentItemMetadataContext context, AuditTrailSiteSettingsPart part) {
|
||||
context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Audit Trail")));
|
||||
}
|
||||
|
||||
private void SetupLazyFields(ActivatedContentContext context, AuditTrailSiteSettingsPart part) {
|
||||
part._eventProviderSettingsField.Loader(() => DeserializeProviderConfiguration(part.Retrieve<string>("Events")));
|
||||
part._eventProviderSettingsField.Setter(value => {
|
||||
part.Store("Events", SerializeProviderConfiguration(value));
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<AuditTrailEventSetting> DeserializeProviderConfiguration(string data) {
|
||||
if (String.IsNullOrWhiteSpace(data))
|
||||
return Enumerable.Empty<AuditTrailEventSetting>();
|
||||
|
||||
try {
|
||||
var doc = XDocument.Parse(data);
|
||||
return doc.Element("Events").Elements("Event").Select(x => new AuditTrailEventSetting {
|
||||
EventName = x.Attr<string>("Name"),
|
||||
IsEnabled = x.Attr<bool>("IsEnabled")
|
||||
}).ToArray();
|
||||
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Error occurred during deserialization of audit trail settings.");
|
||||
}
|
||||
return Enumerable.Empty<AuditTrailEventSetting>();
|
||||
}
|
||||
|
||||
private string SerializeProviderConfiguration(IEnumerable<AuditTrailEventSetting> settings) {
|
||||
var doc = new XDocument(
|
||||
new XElement("Events",
|
||||
settings.Select(x =>
|
||||
new XElement("Event",
|
||||
new XAttribute("Name", x.EventName),
|
||||
new XAttribute("IsEnabled", x.IsEnabled)))));
|
||||
|
||||
return doc.ToString(SaveOptions.DisableFormatting);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,12 @@ namespace Orchard.AuditTrail {
|
||||
.Attachable()
|
||||
.WithDescription("Enables the user to enter a comment about the change when saving a content item."));
|
||||
|
||||
ContentDefinitionManager.AlterPartDefinition("AuditTrailSiteSettingsPart", part => part
|
||||
.Attachable(false)
|
||||
.WithDescription("Stores the audit trail settings."));
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Site", type => type.WithPart("AuditTrailSiteSettingsPart"));
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
public class AuditTrailEventSetting {
|
||||
public string EventName { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Common.Utilities;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
public class AuditTrailSiteSettingsPart : ContentPart {
|
||||
internal LazyField<IEnumerable<AuditTrailEventSetting>> _eventProviderSettingsField = new LazyField<IEnumerable<AuditTrailEventSetting>>();
|
||||
|
||||
public bool AutoTrim {
|
||||
get { return this.Retrieve(x => x.AutoTrim, defaultValue: false); }
|
||||
set { this.Store(x => x.AutoTrim, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Threshold in days.
|
||||
/// </summary>
|
||||
public int AutoTrimThreshold {
|
||||
get { return this.Retrieve(x => x.AutoTrimThreshold, defaultValue: 10); }
|
||||
set { this.Store(x => x.AutoTrimThreshold, value); }
|
||||
}
|
||||
|
||||
public IEnumerable<AuditTrailEventSetting> EventSettings {
|
||||
get { return _eventProviderSettingsField.Value; }
|
||||
set { _eventProviderSettingsField.Value = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,7 @@
|
||||
<Content Include="Views\AuditTrailEvent-ContentPart-FieldRemoved.SummaryAdmin.cshtml" />
|
||||
<Content Include="Views\AuditTrailEvent-ContentType-PartSettingsUpdated.SummaryAdmin.cshtml" />
|
||||
<Content Include="Views\AuditTrailEvent-ContentPart-FieldSettingsUpdated.SummaryAdmin.cshtml" />
|
||||
<Content Include="Views\EditorTemplates\Parts.AuditTrailSiteSettings.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
||||
@@ -117,7 +118,14 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AdminMenu.cs" />
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="Drivers\AuditTrailSiteSettingsPartDriver.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailCategorySettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailEventSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailSiteSettingsViewModel.cs" />
|
||||
<Compile Include="Drivers\ContentsDriver.cs" />
|
||||
<Compile Include="Handlers\AuditTrailSiteSettingsPartHandler.cs" />
|
||||
<Compile Include="Models\AuditTrailEventSetting.cs" />
|
||||
<Compile Include="Models\AuditTrailSiteSettingsPart.cs" />
|
||||
<Compile Include="Providers\ContentDefinition\ContentDefinitionEventHandler.cs" />
|
||||
<Compile Include="Providers\ContentDefinition\GlobalContentDefinitionEditorEvents.cs" />
|
||||
<Compile Include="Providers\ContentDefinition\ContentPartAuditTrailEventProvider.cs" />
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<Placement>
|
||||
<Place Parts_AuditTrail_Comment="Content:after.1"
|
||||
Parts_AuditTrail_Link="Content:after.2"
|
||||
Parts_AuditTrail="Content:after.3"/>
|
||||
|
||||
Parts_AuditTrail="Content:after.3"
|
||||
Parts_AuditTrailSiteSettings_Edit="Content:0"/>
|
||||
|
||||
<Match DisplayType="SummaryAdmin">
|
||||
<Place Parts_Contents_AuditTrail_SummaryAdmin="Actions:7"/>
|
||||
</Match>
|
||||
|
||||
@@ -10,9 +10,14 @@
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.audit-trail-list .audit-trail-record .event-details {
|
||||
}
|
||||
|
||||
.audit-trail-record-details fieldset legend span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.audit-trail-site-settings table th.event-name {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.audit-trail-site-settings table th.event-enabled {
|
||||
width: 60px;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailCategorySettingsViewModel {
|
||||
public string Category { get; set; }
|
||||
public LocalizedString Name { get; set; }
|
||||
public IList<AuditTrailEventSettingsViewModel> Events { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailEventSettingsViewModel {
|
||||
public string Event { get; set; }
|
||||
public LocalizedString Name { get; set; }
|
||||
public LocalizedString Description { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailSiteSettingsViewModel {
|
||||
public bool AutoTrim { get; set; }
|
||||
public int AutoTrimThreshold { get; set; }
|
||||
public IList<AuditTrailCategorySettingsViewModel> Categories { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
@model Orchard.AuditTrail.ViewModels.AuditTrailSiteSettingsViewModel
|
||||
@{
|
||||
Style.Include("admin.css");
|
||||
}
|
||||
<div class="audit-trail-site-settings">
|
||||
<fieldset>
|
||||
<legend>@T("Auto Trim Settings")</legend>
|
||||
<div>
|
||||
@Html.CheckBoxFor(m => m.AutoTrim)
|
||||
@Html.LabelFor(m => m.AutoTrim, T("Automatically trim the audit trail for this site").Text, new { @class = "forcheckbox" })
|
||||
<span class="hint">@T("Check this option to automatically trim the audit trail.")</span>
|
||||
</div>
|
||||
<div id="auditTrailAutoTrimthresholdSetting">
|
||||
@Html.LabelFor(m => m.AutoTrimThreshold, T("Auto-trim threshold"))
|
||||
@Html.TextBoxFor(m => m.AutoTrimThreshold, new { @class = "text small" })
|
||||
<span class="hint">@T("Specify the number of days of audit log data to retain.")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>@T("Specify the events to audit")</legend>
|
||||
@{
|
||||
var i = 0;
|
||||
}
|
||||
@foreach (var category in Model.Categories) {
|
||||
<fieldset>
|
||||
<legend>@category.Name</legend>
|
||||
<input type="hidden" name="AuditTrailSiteSettingsPart.Categories[@i].Category" value="@category.Category" />
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="event-name">@T("Event")</th>
|
||||
<th>@T("Description")</th>
|
||||
<th class="event-enabled">@T("Enabled")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@{ var j = 0; }
|
||||
@foreach (var evnt in category.Events) {
|
||||
var checkboxId = String.Format("Event{0}{1}", i, j);
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" name="AuditTrailSiteSettingsPart.Categories[@i].Events[@j].Event" value="@evnt.Event" />
|
||||
@evnt.Name
|
||||
</td>
|
||||
<td>@evnt.Description</td>
|
||||
<td>
|
||||
<input type="checkbox" id="@checkboxId" name="AuditTrailSiteSettingsPart.Categories[@i].Events[@j].IsEnabled" value="@Boolean.TrueString" @if(evnt.IsEnabled){<text>checked="checked"</text>} />
|
||||
</td>
|
||||
</tr>
|
||||
j++;
|
||||
}
|
||||
</table>
|
||||
</fieldset>
|
||||
i++;
|
||||
}
|
||||
</fieldset>
|
||||
</div>
|
||||
Reference in New Issue
Block a user