mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-27 04:19:04 +08:00
Adding support for client IP address logging.
This commit is contained in:
@@ -48,7 +48,8 @@ namespace Orchard.AuditTrail.Drivers {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var viewModel = new AuditTrailSettingsViewModel {
|
var viewModel = new AuditTrailSettingsViewModel {
|
||||||
Categories = categoriesQuery.ToList()
|
Categories = categoriesQuery.ToList(),
|
||||||
|
EnableClientIpAddressLogging = part.EnableClientIpAddressLogging
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the settings as we may have added new settings.
|
// Update the settings as we may have added new settings.
|
||||||
@@ -58,12 +59,13 @@ namespace Orchard.AuditTrail.Drivers {
|
|||||||
var eventsDictionary = _auditTrailManager.DescribeProviders().Describe().SelectMany(x => x.Events).ToDictionary(x => x.Event);
|
var eventsDictionary = _auditTrailManager.DescribeProviders().Describe().SelectMany(x => x.Events).ToDictionary(x => x.Event);
|
||||||
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||||
foreach (var eventSettingViewModel in viewModel.Categories.SelectMany(x => x.Events)) {
|
foreach (var eventSettingViewModel in viewModel.Categories.SelectMany(x => x.Events)) {
|
||||||
var eventSetting = eventSettings.FirstOrDefault(x => x.EventName == eventSettingViewModel.Event);
|
var eventSetting = eventSettings.First(x => x.EventName == eventSettingViewModel.Event);
|
||||||
var descriptor = eventsDictionary[eventSetting.EventName];
|
var descriptor = eventsDictionary[eventSetting.EventName];
|
||||||
|
|
||||||
eventSetting.IsEnabled = eventSettingViewModel.IsEnabled || descriptor.IsMandatory;
|
eventSetting.IsEnabled = eventSettingViewModel.IsEnabled || descriptor.IsMandatory;
|
||||||
}
|
}
|
||||||
part.EventSettings = eventSettings;
|
part.EventSettings = eventSettings;
|
||||||
|
part.EnableClientIpAddressLogging = viewModel.EnableClientIpAddressLogging;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Orchard.AuditTrail.Models;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.Drivers;
|
||||||
|
using Orchard.Security;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Drivers {
|
||||||
|
public class ClientIpAddressSettingsPartDriver : ContentPartDriver<ClientIpAddressSettingsPart> {
|
||||||
|
private readonly IAuthorizer _authorizer;
|
||||||
|
|
||||||
|
public ClientIpAddressSettingsPartDriver(IAuthorizer authorizer) {
|
||||||
|
_authorizer = authorizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DriverResult Editor(ClientIpAddressSettingsPart part, dynamic shapeHelper) {
|
||||||
|
return Editor(part, null, shapeHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DriverResult Editor(ClientIpAddressSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||||
|
if (!_authorizer.Authorize(Permissions.ManageClientIpAddressSettings))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return ContentShape("Parts_ClientIpAddressSettings_Edit", () => {
|
||||||
|
if (updater != null) {
|
||||||
|
updater.TryUpdateModel(part, Prefix, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shapeHelper.EditorTemplate(TemplateName: "Parts.ClientIpAddressSettings", Model: part, Prefix: Prefix);
|
||||||
|
}).OnGroup("Audit Trail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using Orchard.AuditTrail.Models;
|
using Orchard.AuditTrail.Models;
|
||||||
using Orchard.AuditTrail.Providers.AuditTrail;
|
using Orchard.AuditTrail.Providers.AuditTrail;
|
||||||
using Orchard.AuditTrail.Services;
|
using Orchard.AuditTrail.Services;
|
||||||
@@ -9,7 +6,6 @@ using Orchard.Caching;
|
|||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.ContentManagement.Handlers;
|
using Orchard.ContentManagement.Handlers;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
|
||||||
|
|
||||||
namespace Orchard.AuditTrail.Handlers {
|
namespace Orchard.AuditTrail.Handlers {
|
||||||
public class AuditTrailSettingsPartHandler : ContentHandler {
|
public class AuditTrailSettingsPartHandler : ContentHandler {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Orchard.AuditTrail.Models;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.Handlers;
|
||||||
|
using Orchard.Localization;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Handlers {
|
||||||
|
public class ClientIpAddressSettingsPartHandler : ContentHandler {
|
||||||
|
|
||||||
|
public ClientIpAddressSettingsPartHandler() {
|
||||||
|
Filters.Add(new ActivatingFilter<ClientIpAddressSettingsPart>("Site"));
|
||||||
|
OnGetContentItemMetadata<ClientIpAddressSettingsPart>((context, part) => context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Audit Trail"))));
|
||||||
|
T = NullLocalizer.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Localizer T { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,13 +17,20 @@ namespace Orchard.AuditTrail {
|
|||||||
.Column<string>("EventData", c => c.Unlimited())
|
.Column<string>("EventData", c => c.Unlimited())
|
||||||
.Column<string>("EventFilterKey", c => c.WithLength(16))
|
.Column<string>("EventFilterKey", c => c.WithLength(16))
|
||||||
.Column<string>("EventFilterData", c => c.WithLength(256))
|
.Column<string>("EventFilterData", c => c.WithLength(256))
|
||||||
.Column<string>("Comment", c => c.Unlimited()));
|
.Column<string>("Comment", c => c.Unlimited())
|
||||||
|
.Column<string>("ClientIpAddress", c => c.WithLength(46)));
|
||||||
|
|
||||||
ContentDefinitionManager.AlterPartDefinition("AuditTrailPart", part => part
|
ContentDefinitionManager.AlterPartDefinition("AuditTrailPart", part => part
|
||||||
.Attachable()
|
.Attachable()
|
||||||
.WithDescription("Enables the user to enter a comment about the change when saving a content item."));
|
.WithDescription("Enables the user to enter a comment about the change when saving a content item."));
|
||||||
|
|
||||||
return 1;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UpdateFrom1() {
|
||||||
|
SchemaBuilder.AlterTable("AuditTrailEventRecord", table => table
|
||||||
|
.AddColumn<string>("ClientIpAddress", c => c.WithLength(46)));
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,5 +17,6 @@ namespace Orchard.AuditTrail.Models {
|
|||||||
|
|
||||||
[StringLengthMax]
|
[StringLengthMax]
|
||||||
public virtual string Comment { get; set; }
|
public virtual string Comment { get; set; }
|
||||||
|
public virtual string ClientIpAddress { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,5 +10,10 @@ namespace Orchard.AuditTrail.Models {
|
|||||||
get { return _eventProviderSettingsField.Value; }
|
get { return _eventProviderSettingsField.Value; }
|
||||||
set { _eventProviderSettingsField.Value = value; }
|
set { _eventProviderSettingsField.Value = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool EnableClientIpAddressLogging {
|
||||||
|
get { return this.Retrieve(x => x.EnableClientIpAddressLogging); }
|
||||||
|
set { this.Store(x => x.EnableClientIpAddressLogging, value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Models {
|
||||||
|
public class ClientIpAddressSettingsPart : ContentPart {
|
||||||
|
|
||||||
|
public bool EnableClientIpAddressHeader {
|
||||||
|
get { return this.Retrieve(x => x.EnableClientIpAddressHeader); }
|
||||||
|
set { this.Store(x => x.EnableClientIpAddressHeader, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ClientIpAddressHeaderName {
|
||||||
|
get { return this.Retrieve(x => x.ClientIpAddressHeaderName, "X-Forwarded-For"); }
|
||||||
|
set { this.Store(x => x.ClientIpAddressHeaderName, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -184,8 +184,10 @@
|
|||||||
<Compile Include="AdminMenu.cs" />
|
<Compile Include="AdminMenu.cs" />
|
||||||
<Compile Include="Controllers\ContentController.cs" />
|
<Compile Include="Controllers\ContentController.cs" />
|
||||||
<Compile Include="Controllers\AdminController.cs" />
|
<Compile Include="Controllers\AdminController.cs" />
|
||||||
|
<Compile Include="Drivers\ClientIpAddressSettingsPartDriver.cs" />
|
||||||
<Compile Include="Drivers\AuditTrailTrimmingSettingsPartDriver.cs" />
|
<Compile Include="Drivers\AuditTrailTrimmingSettingsPartDriver.cs" />
|
||||||
<Compile Include="Drivers\AuditTrailSettingsPartDriver.cs" />
|
<Compile Include="Drivers\AuditTrailSettingsPartDriver.cs" />
|
||||||
|
<Compile Include="Handlers\ClientIpAddressSettingsPartHandler.cs" />
|
||||||
<Compile Include="Handlers\AuditTrailTrimmingSettingsPartHandler.cs" />
|
<Compile Include="Handlers\AuditTrailTrimmingSettingsPartHandler.cs" />
|
||||||
<Compile Include="Helpers\FiltersExtensions.cs" />
|
<Compile Include="Helpers\FiltersExtensions.cs" />
|
||||||
<Compile Include="Helpers\DateTimeExtensions.cs" />
|
<Compile Include="Helpers\DateTimeExtensions.cs" />
|
||||||
@@ -197,11 +199,14 @@
|
|||||||
<Compile Include="ImportExport\AuditTrailExportHandler.cs" />
|
<Compile Include="ImportExport\AuditTrailExportHandler.cs" />
|
||||||
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
||||||
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
||||||
|
<Compile Include="Models\ClientIpAddressSettingsPart.cs" />
|
||||||
<Compile Include="Models\AuditTrailTrimmingSettingsPart.cs" />
|
<Compile Include="Models\AuditTrailTrimmingSettingsPart.cs" />
|
||||||
<Compile Include="Providers\AuditTrail\AuditTrailTrimmingSettingsEventProvider.cs" />
|
<Compile Include="Providers\AuditTrail\AuditTrailTrimmingSettingsEventProvider.cs" />
|
||||||
<Compile Include="Providers\AuditTrail\AuditTrailSettingsEventProvider.cs" />
|
<Compile Include="Providers\AuditTrail\AuditTrailSettingsEventProvider.cs" />
|
||||||
<Compile Include="Providers\ContentDefinition\Shapes\ContentPartImportedEventShape.cs" />
|
<Compile Include="Providers\ContentDefinition\Shapes\ContentPartImportedEventShape.cs" />
|
||||||
<Compile Include="Providers\ContentDefinition\Shapes\ContentTypeImportedEventShape.cs" />
|
<Compile Include="Providers\ContentDefinition\Shapes\ContentTypeImportedEventShape.cs" />
|
||||||
|
<Compile Include="Services\DefaultClientIpAddressProvider.cs" />
|
||||||
|
<Compile Include="Services\IClientIpAddressProvider.cs" />
|
||||||
<Compile Include="Services\Models\AuditTrailSettingsContext.cs" />
|
<Compile Include="Services\Models\AuditTrailSettingsContext.cs" />
|
||||||
<Compile Include="Services\CommonAuditTrailEventHandler.cs" />
|
<Compile Include="Services\CommonAuditTrailEventHandler.cs" />
|
||||||
<Compile Include="Services\AuditTrailEventHandlerBase.cs" />
|
<Compile Include="Services\AuditTrailEventHandlerBase.cs" />
|
||||||
@@ -294,7 +299,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Views\EditorTemplates\Parts.AuditTrail.Comment.cshtml" />
|
<Content Include="Views\EditorTemplates\Parts.AuditTrail.Comment.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<Content Include="Views\EditorTemplates\Parts.ClientIpAddressSettings.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Orchard.AuditTrail {
|
|||||||
public static readonly Permission ViewAuditTrail = new Permission { Description = "View audit trail", Name = "ViewAuditTrail" };
|
public static readonly Permission ViewAuditTrail = new Permission { Description = "View audit trail", Name = "ViewAuditTrail" };
|
||||||
public static readonly Permission ManageAuditTrailSettings = new Permission { Description = "Manage audit trail settings", Name = "ManageAuditTrailSettings" };
|
public static readonly Permission ManageAuditTrailSettings = new Permission { Description = "Manage audit trail settings", Name = "ManageAuditTrailSettings" };
|
||||||
public static readonly Permission ImportAuditTrail = new Permission { Description = "Import audit trail", Name = "ImportAuditTrail" };
|
public static readonly Permission ImportAuditTrail = new Permission { Description = "Import audit trail", Name = "ImportAuditTrail" };
|
||||||
|
public static readonly Permission ManageClientIpAddressSettings = new Permission { Description = "Manage client IP address settings", Name = "ManageClientIpAddressSettings" };
|
||||||
|
|
||||||
public virtual Feature Feature { get; set; }
|
public virtual Feature Feature { get; set; }
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ namespace Orchard.AuditTrail {
|
|||||||
yield return ViewAuditTrail;
|
yield return ViewAuditTrail;
|
||||||
yield return ManageAuditTrailSettings;
|
yield return ManageAuditTrailSettings;
|
||||||
yield return ImportAuditTrail;
|
yield return ImportAuditTrail;
|
||||||
|
yield return ManageClientIpAddressSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
|
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
|
||||||
@@ -22,7 +24,8 @@ namespace Orchard.AuditTrail {
|
|||||||
Permissions = new[] {
|
Permissions = new[] {
|
||||||
ViewAuditTrail,
|
ViewAuditTrail,
|
||||||
ManageAuditTrailSettings,
|
ManageAuditTrailSettings,
|
||||||
/* Not even an administrator will get the ImportAuditTrail permission. */
|
ManageClientIpAddressSettings,
|
||||||
|
/* Not even an administrator will get the ImportAuditTrail permission by default. */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
Parts_AuditTrail_Link="Content:after.2"
|
Parts_AuditTrail_Link="Content:after.2"
|
||||||
Parts_AuditTrail="Content:after.3"
|
Parts_AuditTrail="Content:after.3"
|
||||||
Parts_AuditTrailSettings_Edit="Content:0"
|
Parts_AuditTrailSettings_Edit="Content:0"
|
||||||
Parts_AuditTrailTrimmingSettings_Edit="Content:1"/>
|
Parts_AuditTrailTrimmingSettings_Edit="Content:3"
|
||||||
|
Parts_ClientIpAddressSettings_Edit="Content:2"/>
|
||||||
|
|
||||||
<Match DisplayType="SummaryAdmin">
|
<Match DisplayType="SummaryAdmin">
|
||||||
<Place Parts_Contents_AuditTrail_SummaryAdmin="Actions:7"/>
|
<Place Parts_Contents_AuditTrail_SummaryAdmin="Actions:7"/>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
private readonly ISiteService _siteService;
|
private readonly ISiteService _siteService;
|
||||||
private readonly ISignals _signals;
|
private readonly ISignals _signals;
|
||||||
private readonly IShapeFactory _shapeFactory;
|
private readonly IShapeFactory _shapeFactory;
|
||||||
|
private readonly IClientIpAddressProvider _clientIpAddressProvider;
|
||||||
|
|
||||||
public AuditTrailManager(
|
public AuditTrailManager(
|
||||||
IRepository<AuditTrailEventRecord> auditTrailRepository,
|
IRepository<AuditTrailEventRecord> auditTrailRepository,
|
||||||
@@ -36,7 +37,8 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager,
|
||||||
ISiteService siteService,
|
ISiteService siteService,
|
||||||
ISignals signals,
|
ISignals signals,
|
||||||
IShapeFactory shapeFactory) {
|
IShapeFactory shapeFactory,
|
||||||
|
IClientIpAddressProvider clientIpAddressProvider) {
|
||||||
|
|
||||||
_auditTrailRepository = auditTrailRepository;
|
_auditTrailRepository = auditTrailRepository;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
@@ -47,6 +49,7 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
_siteService = siteService;
|
_siteService = siteService;
|
||||||
_signals = signals;
|
_signals = signals;
|
||||||
_shapeFactory = shapeFactory;
|
_shapeFactory = shapeFactory;
|
||||||
|
_clientIpAddressProvider = clientIpAddressProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPageOfItems<AuditTrailEventRecord> GetRecords(
|
public IPageOfItems<AuditTrailEventRecord> GetRecords(
|
||||||
@@ -151,7 +154,8 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
EventData = _serializer.Serialize(context.EventData),
|
EventData = _serializer.Serialize(context.EventData),
|
||||||
EventFilterKey = context.EventFilterKey,
|
EventFilterKey = context.EventFilterKey,
|
||||||
EventFilterData = context.EventFilterData,
|
EventFilterData = context.EventFilterData,
|
||||||
Comment = context.Comment
|
Comment = context.Comment,
|
||||||
|
ClientIpAddress = GetClientIpAddress()
|
||||||
};
|
};
|
||||||
|
|
||||||
_auditTrailRepository.Create(record);
|
_auditTrailRepository.Create(record);
|
||||||
@@ -161,18 +165,6 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEventEnabled(AuditTrailEventDescriptor eventDescriptor) {
|
|
||||||
if (eventDescriptor.IsMandatory)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var settingsDictionary = _cacheManager.Get("AuditTrail.EventSettings", context => {
|
|
||||||
context.Monitor(_signals.When("AuditTrail.EventSettings"));
|
|
||||||
return _siteService.GetSiteSettings().As<AuditTrailSettingsPart>().EventSettings.ToDictionary(x => x.EventName);
|
|
||||||
});
|
|
||||||
var setting = settingsDictionary.ContainsKey(eventDescriptor.Event) ? settingsDictionary[eventDescriptor.Event] : default(AuditTrailEventSetting);
|
|
||||||
return setting != null ? setting.IsEnabled : eventDescriptor.IsEnabledByDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<AuditTrailCategoryDescriptor> DescribeCategories() {
|
public IEnumerable<AuditTrailCategoryDescriptor> DescribeCategories() {
|
||||||
var context = DescribeProviders();
|
var context = DescribeProviders();
|
||||||
return context.Describe();
|
return context.Describe();
|
||||||
@@ -245,5 +237,26 @@ namespace Orchard.AuditTrail.Services {
|
|||||||
}
|
}
|
||||||
return Enumerable.Empty<AuditTrailEventSetting>();
|
return Enumerable.Empty<AuditTrailEventSetting>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetClientIpAddress() {
|
||||||
|
var settings = _siteService.GetSiteSettings().As<AuditTrailSettingsPart>();
|
||||||
|
|
||||||
|
if (!settings.EnableClientIpAddressLogging)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return _clientIpAddressProvider.GetClientIpAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsEventEnabled(AuditTrailEventDescriptor eventDescriptor) {
|
||||||
|
if (eventDescriptor.IsMandatory)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var settingsDictionary = _cacheManager.Get("AuditTrail.EventSettings", context => {
|
||||||
|
context.Monitor(_signals.When("AuditTrail.EventSettings"));
|
||||||
|
return _siteService.GetSiteSettings().As<AuditTrailSettingsPart>().EventSettings.ToDictionary(x => x.EventName);
|
||||||
|
});
|
||||||
|
var setting = settingsDictionary.ContainsKey(eventDescriptor.Event) ? settingsDictionary[eventDescriptor.Event] : default(AuditTrailEventSetting);
|
||||||
|
return setting != null ? setting.IsEnabled : eventDescriptor.IsEnabledByDefault;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Orchard.AuditTrail.Models;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Services {
|
||||||
|
public class DefaultClientIpAddressProvider : IClientIpAddressProvider {
|
||||||
|
private readonly IWorkContextAccessor _wca;
|
||||||
|
public DefaultClientIpAddressProvider(IWorkContextAccessor wca) {
|
||||||
|
_wca = wca;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetClientIpAddress() {
|
||||||
|
var workContext = _wca.GetContext();
|
||||||
|
var settings = workContext.CurrentSite.As<ClientIpAddressSettingsPart>();
|
||||||
|
var address = workContext.HttpContext.Request.UserHostAddress;
|
||||||
|
|
||||||
|
if (settings.EnableClientIpAddressHeader && !String.IsNullOrWhiteSpace(settings.ClientIpAddressHeaderName)) {
|
||||||
|
var headerName = settings.ClientIpAddressHeaderName.Trim();
|
||||||
|
var customAddresses = ParseAddresses(workContext.HttpContext.Request.Headers[headerName]).ToArray();
|
||||||
|
|
||||||
|
if (customAddresses.Any())
|
||||||
|
address = customAddresses.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> ParseAddresses(string value) {
|
||||||
|
return !String.IsNullOrWhiteSpace(value)
|
||||||
|
? value.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())
|
||||||
|
: Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Orchard.AuditTrail.Services {
|
||||||
|
public interface IClientIpAddressProvider : IDependency {
|
||||||
|
string GetClientIpAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,5 +3,6 @@ using System.Collections.Generic;
|
|||||||
namespace Orchard.AuditTrail.ViewModels {
|
namespace Orchard.AuditTrail.ViewModels {
|
||||||
public class AuditTrailSettingsViewModel {
|
public class AuditTrailSettingsViewModel {
|
||||||
public IList<AuditTrailCategorySettingsViewModel> Categories { get; set; }
|
public IList<AuditTrailCategorySettingsViewModel> Categories { get; set; }
|
||||||
|
public bool EnableClientIpAddressLogging { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
@model Orchard.AuditTrail.ViewModels.AuditTrailDetailsViewModel
|
@using Orchard.AuditTrail.Models
|
||||||
|
@using Orchard.ContentManagement
|
||||||
|
@model Orchard.AuditTrail.ViewModels.AuditTrailDetailsViewModel
|
||||||
@{
|
@{
|
||||||
Style.Include("audittrail-display.css");
|
Style.Include("audittrail-display.css");
|
||||||
|
|
||||||
var record = Model.Record;
|
var record = Model.Record;
|
||||||
var descriptor = Model.Descriptor;
|
var descriptor = Model.Descriptor;
|
||||||
|
var enablieClientIpAddressLogging = WorkContext.CurrentSite.As<AuditTrailSettingsPart>().EnableClientIpAddressLogging;
|
||||||
|
|
||||||
Layout.Title = T("Audit Trail Event");
|
Layout.Title = T("Audit Trail Event");
|
||||||
}
|
}
|
||||||
@@ -12,6 +15,10 @@
|
|||||||
@T("Category:") <strong>@descriptor.CategoryDescriptor.Name</strong><br />
|
@T("Category:") <strong>@descriptor.CategoryDescriptor.Name</strong><br />
|
||||||
@T("Timestamp:") <strong>@Display.DateTime(DateTimeUtc: record.CreatedUtc)</strong><br />
|
@T("Timestamp:") <strong>@Display.DateTime(DateTimeUtc: record.CreatedUtc)</strong><br />
|
||||||
@T("Username:") <strong>@record.UserName</strong>
|
@T("Username:") <strong>@record.UserName</strong>
|
||||||
|
@if (enablieClientIpAddressLogging) {
|
||||||
|
<br/>
|
||||||
|
@T("Client IP Address:") <strong>@record.ClientIpAddress</strong>
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
<section class="audittrail-event-details-section">
|
<section class="audittrail-event-details-section">
|
||||||
@Display(Model.DetailsShape)
|
@Display(Model.DetailsShape)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
@using Orchard.AuditTrail.Helpers
|
@using Orchard.AuditTrail.Helpers
|
||||||
|
@using Orchard.AuditTrail.Models
|
||||||
@using Orchard.AuditTrail.Services.Models
|
@using Orchard.AuditTrail.Services.Models
|
||||||
|
@using Orchard.ContentManagement
|
||||||
@model Orchard.AuditTrail.ViewModels.AuditTrailViewModel
|
@model Orchard.AuditTrail.ViewModels.AuditTrailViewModel
|
||||||
@{
|
@{
|
||||||
Style.Include("audittrail-display.css");
|
Style.Include("audittrail-display.css");
|
||||||
@@ -10,6 +12,7 @@
|
|||||||
new SelectListItem {Text = T("Category (alphabetical)").Text, Value = AuditTrailOrderBy.CategoryAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.CategoryAscending},
|
new SelectListItem {Text = T("Category (alphabetical)").Text, Value = AuditTrailOrderBy.CategoryAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.CategoryAscending},
|
||||||
new SelectListItem {Text = T("Event name (alphabetical)").Text, Value = AuditTrailOrderBy.EventAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.EventAscending},
|
new SelectListItem {Text = T("Event name (alphabetical)").Text, Value = AuditTrailOrderBy.EventAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.EventAscending},
|
||||||
};
|
};
|
||||||
|
var enablieClientIpAddressLogging = WorkContext.CurrentSite.As<AuditTrailSettingsPart>().EnableClientIpAddressLogging;
|
||||||
|
|
||||||
Layout.Title = T("Audit Trail");
|
Layout.Title = T("Audit Trail");
|
||||||
}
|
}
|
||||||
@@ -38,6 +41,9 @@
|
|||||||
<th class="category-column">@T("Category")</th>
|
<th class="category-column">@T("Category")</th>
|
||||||
<th class="event-column">@T("Event")</th>
|
<th class="event-column">@T("Event")</th>
|
||||||
<th class="user-column">@T("User")</th>
|
<th class="user-column">@T("User")</th>
|
||||||
|
@if (enablieClientIpAddressLogging) {
|
||||||
|
<th class="client-ip-address-column">@T("Client IP Address")</th>
|
||||||
|
}
|
||||||
<th class="timestamp-column">@T("Timestamp")</th>
|
<th class="timestamp-column">@T("Timestamp")</th>
|
||||||
<th class="summary-column">@T("Summary")</th>
|
<th class="summary-column">@T("Summary")</th>
|
||||||
<th class="comment-column">@T("Comment")</th>
|
<th class="comment-column">@T("Comment")</th>
|
||||||
@@ -50,6 +56,9 @@
|
|||||||
<td class="category-column">@record.CategoryDescriptor.Name</td>
|
<td class="category-column">@record.CategoryDescriptor.Name</td>
|
||||||
<td class="event-column">@record.EventDescriptor.Name</td>
|
<td class="event-column">@record.EventDescriptor.Name</td>
|
||||||
<td class="user-column">@record.Record.UserName</td>
|
<td class="user-column">@record.Record.UserName</td>
|
||||||
|
@if (enablieClientIpAddressLogging) {
|
||||||
|
<td class="client-ip-address-column">@record.Record.ClientIpAddress</td>
|
||||||
|
}
|
||||||
<td class="timestamp-column">@Display.DateTime(DateTimeUtc: record.Record.CreatedUtc)</td>
|
<td class="timestamp-column">@Display.DateTime(DateTimeUtc: record.Record.CreatedUtc)</td>
|
||||||
<td class="summary-column">@Display(record.SummaryShape)</td>
|
<td class="summary-column">@Display(record.SummaryShape)</td>
|
||||||
<td class="comment-column">@Html.Raw(record.Record.Comment.NewlinesToHtml())</td>
|
<td class="comment-column">@Html.Raw(record.Record.Comment.NewlinesToHtml())</td>
|
||||||
|
|||||||
@@ -46,7 +46,15 @@
|
|||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
</table>
|
</table>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>@T("Client IP address logging")</h2>
|
||||||
|
<div>
|
||||||
|
@Html.CheckBoxFor(m => m.EnableClientIpAddressLogging)
|
||||||
|
@Html.LabelFor(m => m.EnableClientIpAddressLogging, T("Enable client IP address logging").Text, new { @class = "forcheckbox" })
|
||||||
|
<span class="hint">@T("When enabled, the client IP address will be recorded as part of an audit trail event.")</span>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
@model Orchard.AuditTrail.Models.ClientIpAddressSettingsPart
|
||||||
|
@{
|
||||||
|
Script.Require("ShapesBase");
|
||||||
|
}
|
||||||
|
<section class="clientipaddress-settings-section">
|
||||||
|
<fieldset>
|
||||||
|
@Html.CheckBoxFor(m => m.EnableClientIpAddressHeader)
|
||||||
|
@Html.LabelFor(m => m.EnableClientIpAddressHeader, T("Enable client IP address header").Text, new { @class = "forcheckbox" })
|
||||||
|
<span class="hint">@T("Enable this when running behind a reverse proxy server.")</span>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset data-controllerid="@Html.FieldIdFor(m => m.EnableClientIpAddressHeader)">
|
||||||
|
@Html.LabelFor(m => m.ClientIpAddressHeaderName, T("Client IP address header name"))
|
||||||
|
@Html.TextBoxFor(m => m.ClientIpAddressHeaderName, new { @class = "text medium" })
|
||||||
|
<span class="hint">@T("The client IP address header name to check for. Ususally this is the <em>X-Forwarded-For</em> header.")</span>
|
||||||
|
</fieldset>
|
||||||
|
</section>
|
||||||
Reference in New Issue
Block a user