mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
#21237: Moved IClientIpAddressProvider into Orchard.Framework.
This changeset also renames the service to IClientAddressAccessor and refactors the settings into being configurable from HostComponents instead of through a site settings part. Work Item: 21237
This commit is contained in:
@@ -94,5 +94,16 @@
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
<Component Type="Orchard.Services.ClientAddressAccessor">
|
||||
<Properties>
|
||||
<!-- Set Value="true" to read the client host address from the specified HTTP header. -->
|
||||
<Property Name="EnableClientAddressHeader" Value="false"/>
|
||||
|
||||
<!-- Set Value to the HTTP header name from which to read the client host address. Only used when EnableClientAddressHeader="true".
|
||||
If the specified header was not found, the system will fall back to the user host address as provided by the Request object.-->
|
||||
<Property Name="ClientAddressHeaderName" Value="X-Forwarded-For"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
</Components>
|
||||
</HostComponents>
|
||||
|
@@ -1,31 +0,0 @@
|
||||
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,17 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
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); }
|
||||
}
|
||||
}
|
||||
}
|
@@ -200,10 +200,8 @@
|
||||
<Compile Include="Services\IRecycleBin.cs" />
|
||||
<Compile Include="Services\RecycleBin.cs" />
|
||||
<Compile Include="ViewModels\RecycleBinViewModel.cs" />
|
||||
<Compile Include="Drivers\ClientIpAddressSettingsPartDriver.cs" />
|
||||
<Compile Include="Drivers\AuditTrailTrimmingSettingsPartDriver.cs" />
|
||||
<Compile Include="Drivers\AuditTrailSettingsPartDriver.cs" />
|
||||
<Compile Include="Handlers\ClientIpAddressSettingsPartHandler.cs" />
|
||||
<Compile Include="Handlers\AuditTrailTrimmingSettingsPartHandler.cs" />
|
||||
<Compile Include="Helpers\FiltersExtensions.cs" />
|
||||
<Compile Include="Helpers\DateTimeExtensions.cs" />
|
||||
@@ -215,14 +213,11 @@
|
||||
<Compile Include="ImportExport\AuditTrailExportHandler.cs" />
|
||||
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
||||
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
||||
<Compile Include="Models\ClientIpAddressSettingsPart.cs" />
|
||||
<Compile Include="Models\AuditTrailTrimmingSettingsPart.cs" />
|
||||
<Compile Include="Providers\AuditTrail\AuditTrailTrimmingSettingsEventProvider.cs" />
|
||||
<Compile Include="Providers\AuditTrail\AuditTrailSettingsEventProvider.cs" />
|
||||
<Compile Include="Providers\ContentDefinition\Shapes\ContentPartImportedEventShape.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\CommonAuditTrailEventHandler.cs" />
|
||||
<Compile Include="Services\AuditTrailEventHandlerBase.cs" />
|
||||
@@ -316,9 +311,6 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts.AuditTrail.Comment.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts.ClientIpAddressSettings.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\AuditTrailEventActions.cshtml" />
|
||||
</ItemGroup>
|
||||
|
@@ -26,7 +26,7 @@ namespace Orchard.AuditTrail.Services {
|
||||
private readonly ISiteService _siteService;
|
||||
private readonly ISignals _signals;
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly IClientIpAddressProvider _clientIpAddressProvider;
|
||||
private readonly IClientAddressAccessor _clientAddressAccessor;
|
||||
|
||||
public AuditTrailManager(
|
||||
IRepository<AuditTrailEventRecord> auditTrailRepository,
|
||||
@@ -38,7 +38,7 @@ namespace Orchard.AuditTrail.Services {
|
||||
ISiteService siteService,
|
||||
ISignals signals,
|
||||
IShapeFactory shapeFactory,
|
||||
IClientIpAddressProvider clientIpAddressProvider) {
|
||||
IClientAddressAccessor clientAddressAccessor) {
|
||||
|
||||
_auditTrailRepository = auditTrailRepository;
|
||||
_providers = providers;
|
||||
@@ -49,7 +49,7 @@ namespace Orchard.AuditTrail.Services {
|
||||
_siteService = siteService;
|
||||
_signals = signals;
|
||||
_shapeFactory = shapeFactory;
|
||||
_clientIpAddressProvider = clientIpAddressProvider;
|
||||
_clientAddressAccessor = clientAddressAccessor;
|
||||
}
|
||||
|
||||
public IPageOfItems<AuditTrailEventRecord> GetRecords(
|
||||
@@ -155,7 +155,7 @@ namespace Orchard.AuditTrail.Services {
|
||||
EventFilterKey = context.EventFilterKey,
|
||||
EventFilterData = context.EventFilterData,
|
||||
Comment = context.Comment,
|
||||
ClientIpAddress = GetClientIpAddress()
|
||||
ClientIpAddress = GetClientAddress()
|
||||
};
|
||||
|
||||
_auditTrailRepository.Create(record);
|
||||
@@ -238,13 +238,13 @@ namespace Orchard.AuditTrail.Services {
|
||||
return Enumerable.Empty<AuditTrailEventSetting>();
|
||||
}
|
||||
|
||||
private string GetClientIpAddress() {
|
||||
private string GetClientAddress() {
|
||||
var settings = _siteService.GetSiteSettings().As<AuditTrailSettingsPart>();
|
||||
|
||||
if (!settings.EnableClientIpAddressLogging)
|
||||
return null;
|
||||
|
||||
return _clientIpAddressProvider.GetClientIpAddress();
|
||||
return _clientAddressAccessor.GetClientAddress();
|
||||
}
|
||||
|
||||
private bool IsEventEnabled(AuditTrailEventDescriptor eventDescriptor) {
|
||||
|
@@ -1,36 +0,0 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
public interface IClientIpAddressProvider : IDependency {
|
||||
string GetClientIpAddress();
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
@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("Read client IP address from HTTP header instead of network source IP").Text, new { @class = "forcheckbox" })
|
||||
<span class="hint">@T("This can be useful when the site is behind a reverse proxy server.")</span>
|
||||
</fieldset>
|
||||
<fieldset data-controllerid="@Html.FieldIdFor(m => m.EnableClientIpAddressHeader)">
|
||||
@Html.LabelFor(m => m.ClientIpAddressHeaderName, T("Client IP address HTTP header name"))
|
||||
@Html.TextBoxFor(m => m.ClientIpAddressHeaderName, new { @class = "text medium" })
|
||||
<span class="hint">@T("The name of the HTTP header from which to read the client IP address. For most reverse proxy servers this should be <strong>X-Forwarded-For</strong>.")</span>
|
||||
</fieldset>
|
||||
</section>
|
@@ -1,13 +1,13 @@
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.DynamicForms.Elements;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.DynamicForms.Handlers {
|
||||
public class IpAddressFieldHandler : FormElementEventHandlerBase {
|
||||
private readonly IClientIpAddressProvider _clientIpAddressProvider;
|
||||
private readonly IClientAddressAccessor _clientAddressAccessor;
|
||||
|
||||
public IpAddressFieldHandler(IClientIpAddressProvider clientIpAddressProvider) {
|
||||
_clientIpAddressProvider = clientIpAddressProvider;
|
||||
public IpAddressFieldHandler(IClientAddressAccessor clientAddressAccessor) {
|
||||
_clientAddressAccessor = clientAddressAccessor;
|
||||
}
|
||||
|
||||
public override void GetElementValue(FormElement element, ReadElementValuesContext context) {
|
||||
@@ -17,7 +17,7 @@ namespace Orchard.DynamicForms.Handlers {
|
||||
return;
|
||||
|
||||
var key = ipAddressField.Name;
|
||||
context.Output[key] = _clientIpAddressProvider.GetClientIpAddress();
|
||||
context.Output[key] = _clientAddressAccessor.GetClientAddress();
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ Features:
|
||||
Name: Dynamic Forms
|
||||
Description: Create custom forms like contact forms using layouts.
|
||||
Category: Forms
|
||||
Dependencies: Orchard.Layouts, Orchard.Scripting.CSharp, Orchard.Tokens, Orchard.Workflows, Orchard.Users, Orchard.AuditTrail, Orchard.Fields, Common
|
||||
Dependencies: Orchard.Layouts, Orchard.Scripting.CSharp, Orchard.Tokens, Orchard.Workflows, Orchard.Users, Orchard.Fields, Common
|
||||
Orchard.DynamicForms.AntiSpam:
|
||||
Name: Anti-Spam Elements
|
||||
Description: Provides anti-spam elements to protect your content from malicious submissions.
|
||||
|
@@ -118,10 +118,6 @@
|
||||
<Project>{91bc2e7f-da04-421c-98ef-76d37cec130c}</Project>
|
||||
<Name>Orchard.AntiSpam</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.AuditTrail\Orchard.AuditTrail.csproj">
|
||||
<Project>{3dd574cd-9c5d-4a45-85e1-ebba64c22b5f}</Project>
|
||||
<Name>Orchard.AuditTrail</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Fields\Orchard.Fields.csproj">
|
||||
<Project>{3787dde5-e5c8-4841-bda7-dcb325388064}</Project>
|
||||
<Name>Orchard.Fields</Name>
|
||||
|
@@ -349,7 +349,9 @@
|
||||
<Compile Include="Security\CurrentUserWorkContext.cs" />
|
||||
<Compile Include="Security\Providers\DefaultEncryptionService.cs" />
|
||||
<Compile Include="Services\Clock.cs" />
|
||||
<Compile Include="Services\ClientAddressAccessor.cs" />
|
||||
<Compile Include="Services\DefaultJsonConverter.cs" />
|
||||
<Compile Include="Services\IClientAddressAccessor.cs" />
|
||||
<Compile Include="Services\IJsonConverter.cs" />
|
||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||
|
47
src/Orchard/Services/ClientAddressAccessor.cs
Normal file
47
src/Orchard/Services/ClientAddressAccessor.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Services {
|
||||
/// <summary>
|
||||
/// Provides access to the client host address.
|
||||
/// </summary>
|
||||
public class ClientAddressAccessor : IClientAddressAccessor {
|
||||
private readonly IWorkContextAccessor _wca;
|
||||
public ClientAddressAccessor(IWorkContextAccessor wca) {
|
||||
_wca = wca;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the client host address should be read from an HTTP header, specified via <see cref="ClientAddressHeaderName"/>
|
||||
/// </summary>
|
||||
public bool EnableClientAddressHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP header name to read the client host address from if <see cref="EnableClientAddressHeader"/> is set to true.
|
||||
/// If the specified header was not found, the system will fall back to the user host address as provided by the Request object.
|
||||
/// </summary>
|
||||
public string ClientAddressHeaderName { get; set; }
|
||||
|
||||
public string GetClientAddress() {
|
||||
var request = _wca.GetContext().HttpContext.Request;
|
||||
|
||||
if (EnableClientAddressHeader && !String.IsNullOrWhiteSpace(ClientAddressHeaderName)) {
|
||||
var headerName = ClientAddressHeaderName.Trim();
|
||||
var customAddresses = ParseAddresses(request.Headers[headerName]).ToArray();
|
||||
|
||||
if (customAddresses.Any())
|
||||
return customAddresses.First();
|
||||
}
|
||||
|
||||
return request.UserHostAddress;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> ParseAddresses(string value) {
|
||||
return !String.IsNullOrWhiteSpace(value)
|
||||
? value.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())
|
||||
: Enumerable.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
8
src/Orchard/Services/IClientAddressAccessor.cs
Normal file
8
src/Orchard/Services/IClientAddressAccessor.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Orchard.Services {
|
||||
/// <summary>
|
||||
/// Provides access to the user host address.
|
||||
/// </summary>
|
||||
public interface IClientAddressAccessor : IDependency {
|
||||
string GetClientAddress();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user