Skip to content

Commit

Permalink
Merge pull request #998 from colinin/ip-location-session
Browse files Browse the repository at this point in the history
feat(session): add ip geolocation resolution to user sessions
  • Loading branch information
colinin authored Sep 5, 2024
2 parents 5f84a36 + 0fa4b84 commit b83cb49
Show file tree
Hide file tree
Showing 34 changed files with 684,618 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
<PackageVersion Include="Volo.Abp.Users.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Users.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Validation" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.VirtualFileSystem" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<!-- .NET -->
<ItemGroup>
Expand Down Expand Up @@ -222,6 +223,7 @@
<PackageVersion Include="Hangfire.MySqlStorage" Version="2.0.3" />
<PackageVersion Include="HangFire.SqlServer" Version="1.8.14" />
<PackageVersion Include="IdentityModel" Version="6.2.0" />
<PackageVersion Include="IP2Region.Net" Version="2.0.2" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="Markdig" Version="0.34.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
Expand Down
28 changes: 28 additions & 0 deletions aspnet-core/LINGYUN.MicroService.SingleProject.sln
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Work.Han
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.Saas", "modules\saas\LINGYUN.Abp.MultiTenancy.Saas\LINGYUN.Abp.MultiTenancy.Saas.csproj", "{E3C07A77-EAF9-4A3F-8814-7D2F116C8E26}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.IP2Region", "framework\common\LINGYUN.Abp.IP2Region\LINGYUN.Abp.IP2Region.csproj", "{DA54E88E-C43E-4E31-92D0-08A753F2C08D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{A7417E7F-DB97-48DB-B849-AFC15854A6E7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Tests", "tests\LINGYUN.Abp.Aliyun.Tests\LINGYUN.Abp.Aliyun.Tests.csproj", "{8DDE4291-BC57-4C56-9871-B982462F4C3D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.IP2Region.Tests", "tests\LINGYUN.Abp.IP2Region.Tests\LINGYUN.Abp.IP2Region.Tests.csproj", "{C5D64A2B-7E7E-4509-9F31-425D59712E6F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1421,6 +1429,22 @@ Global
{E3C07A77-EAF9-4A3F-8814-7D2F116C8E26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3C07A77-EAF9-4A3F-8814-7D2F116C8E26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3C07A77-EAF9-4A3F-8814-7D2F116C8E26}.Release|Any CPU.Build.0 = Release|Any CPU
{DA54E88E-C43E-4E31-92D0-08A753F2C08D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA54E88E-C43E-4E31-92D0-08A753F2C08D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA54E88E-C43E-4E31-92D0-08A753F2C08D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA54E88E-C43E-4E31-92D0-08A753F2C08D}.Release|Any CPU.Build.0 = Release|Any CPU
{A7417E7F-DB97-48DB-B849-AFC15854A6E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7417E7F-DB97-48DB-B849-AFC15854A6E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7417E7F-DB97-48DB-B849-AFC15854A6E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7417E7F-DB97-48DB-B849-AFC15854A6E7}.Release|Any CPU.Build.0 = Release|Any CPU
{8DDE4291-BC57-4C56-9871-B982462F4C3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DDE4291-BC57-4C56-9871-B982462F4C3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DDE4291-BC57-4C56-9871-B982462F4C3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DDE4291-BC57-4C56-9871-B982462F4C3D}.Release|Any CPU.Build.0 = Release|Any CPU
{C5D64A2B-7E7E-4509-9F31-425D59712E6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5D64A2B-7E7E-4509-9F31-425D59712E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5D64A2B-7E7E-4509-9F31-425D59712E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5D64A2B-7E7E-4509-9F31-425D59712E6F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1684,6 +1708,10 @@ Global
{BB2DF96A-6ED8-4F47-948C-230EA2065C4C} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
{DB80C55F-8B70-4840-942A-ED021ED88BD6} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
{E3C07A77-EAF9-4A3F-8814-7D2F116C8E26} = {ECE6E6D7-A4F6-4F50-BC21-AE2EB14A3129}
{DA54E88E-C43E-4E31-92D0-08A753F2C08D} = {99B7CBDE-A251-4738-97F0-DB1DB484BEE1}
{A7417E7F-DB97-48DB-B849-AFC15854A6E7} = {37E2CAFE-0024-452E-BF81-E15F937E08EF}
{8DDE4291-BC57-4C56-9871-B982462F4C3D} = {37E2CAFE-0024-452E-BF81-E15F937E08EF}
{C5D64A2B-7E7E-4509-9F31-425D59712E6F} = {37E2CAFE-0024-452E-BF81-E15F937E08EF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>
30 changes: 30 additions & 0 deletions aspnet-core/framework/common/LINGYUN.Abp.IP2Region/FodyWeavers.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2023 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// @Author Alan <[email protected]>
// @Date 2023/07/25

using System;
using System.Buffers;
using System.IO;

namespace IP2Region.Net.Internal.Abstractions;

internal abstract class AbstractCacheStrategy
{
protected const int HeaderInfoLength = 256;
protected const int VectorIndexRows = 256;
protected const int VectorIndexCols = 256;
protected const int VectorIndexSize = 8;

protected readonly Stream XdbStream;
private const int BufferSize = 4096;

internal int IoCount { get; private set; }

protected AbstractCacheStrategy(Stream xdbStream)
{
XdbStream = xdbStream;
}

protected int GetVectorIndexStartPos(uint ip)
{
var il0 = ip >> 24 & 0xFF;
var il1 = ip >> 16 & 0xFF;
var idx = il0 * VectorIndexCols * VectorIndexSize + il1 * VectorIndexSize;
return (int)idx;
}

internal abstract ReadOnlyMemory<byte> GetVectorIndex(uint ip);

internal virtual ReadOnlyMemory<byte> GetData(int offset, int length)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(length);
int totalBytesRead = 0;
try
{
XdbStream.Seek(offset, SeekOrigin.Begin);

int bytesRead;
do
{
int bytesToRead = Math.Min(BufferSize, length - totalBytesRead);
bytesRead = XdbStream.Read(buffer, totalBytesRead, bytesToRead);
totalBytesRead += bytesRead;

IoCount++;
} while (bytesRead > 0 && totalBytesRead < length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}

return new ReadOnlyMemory<byte>(buffer, 0, totalBytesRead);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2023 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// @Author Alan <[email protected]>
// @Date 2023/07/25

using IP2Region.Net.Internal.Abstractions;
using IP2Region.Net.XDB;
using System;
using System.IO;

namespace IP2Region.Net.Internal;

internal class CacheStrategyFactory
{
private readonly Stream _xdbStream;

public CacheStrategyFactory(Stream xdbStream)
{
_xdbStream = xdbStream;
}

public AbstractCacheStrategy CreateCacheStrategy(CachePolicy cachePolicy)
{
return cachePolicy switch
{
CachePolicy.Content => new ContentCacheStrategy(_xdbStream),
CachePolicy.VectorIndex => new VectorIndexCacheStrategy(_xdbStream),
CachePolicy.File => new FileCacheStrategy(_xdbStream),
_ => throw new ArgumentException(nameof(cachePolicy))
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// @Author Alan <[email protected]>
// @Date 2023/07/25

using IP2Region.Net.Internal.Abstractions;
using System;
using System.IO;

namespace IP2Region.Net.Internal;

internal class ContentCacheStrategy : AbstractCacheStrategy
{
private readonly ReadOnlyMemory<byte> _cacheData;

public ContentCacheStrategy(Stream xdbStream) : base(xdbStream)
{
_cacheData = base.GetData(0, (int)XdbStream.Length);
XdbStream.Close();
XdbStream.Dispose();
}

internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip)
{
int idx = GetVectorIndexStartPos(ip);
return _cacheData.Slice(HeaderInfoLength + idx, VectorIndexSize);
}

internal override ReadOnlyMemory<byte> GetData(int offset, int length)
{
return _cacheData.Slice(offset, length);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2023 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// @Author Alan <[email protected]>
// @Date 2023/07/25

using IP2Region.Net.Internal.Abstractions;
using System;
using System.IO;

namespace IP2Region.Net.Internal;

internal class FileCacheStrategy : AbstractCacheStrategy
{
public FileCacheStrategy(Stream xdbStream) : base(xdbStream)
{
}

internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip)
{
var idx = GetVectorIndexStartPos(ip);
return GetData(HeaderInfoLength + idx, VectorIndexSize);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2023 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// @Author Alan <[email protected]>
// @Date 2023/07/25

using IP2Region.Net.Internal.Abstractions;
using System;
using System.IO;

namespace IP2Region.Net.Internal;

internal class VectorIndexCacheStrategy : AbstractCacheStrategy
{
private readonly ReadOnlyMemory<byte> _vectorIndex;

public VectorIndexCacheStrategy(Stream xdbStream) : base(xdbStream)
{
var vectorLength = VectorIndexRows * VectorIndexCols * VectorIndexSize;
_vectorIndex = base.GetData(HeaderInfoLength, vectorLength);
}

internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip)
{
var idx = GetVectorIndexStartPos(ip);
return _vectorIndex.Slice(idx, VectorIndexSize);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.IP2Region</AssemblyName>
<PackageId>LINGYUN.Abp.IP2Region</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>

<ItemGroup>
<None Remove="LINGYUN\Abp\IP2Region\Resources\ip2region.xdb" />
<EmbeddedResource Include="LINGYUN\Abp\IP2Region\Resources\ip2region.xdb" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Volo.Abp.VirtualFileSystem" />
<PackageReference Include="IP2Region.Net" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using IP2Region.Net.Abstractions;
using IP2Region.Net.XDB;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;

namespace LINGYUN.Abp.IP2Region;

[DependsOn(typeof(AbpVirtualFileSystemModule))]
public class AbpIP2RegionModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIP2RegionModule>();
});

context.Services.AddSingleton<ISearcher, AbpSearcher>((serviceProvider) =>
{
var virtualFileProvider = serviceProvider.GetRequiredService<IVirtualFileProvider>();
var xdbFile = virtualFileProvider.GetFileInfo("/LINGYUN/Abp/IP2Region/Resources/ip2region.xdb");
var searcher = new AbpSearcher(CachePolicy.File, xdbFile.CreateReadStream());
return searcher;
});
}
}
Loading

0 comments on commit b83cb49

Please sign in to comment.