Skip to content

Commit

Permalink
feat(oss): add Sonatype Nexus integration.
Browse files Browse the repository at this point in the history
  • Loading branch information
colinin committed Oct 11, 2023
1 parent ca9318e commit ad2176e
Show file tree
Hide file tree
Showing 76 changed files with 2,410 additions and 0 deletions.
38 changes: 38 additions & 0 deletions aspnet-core/LINGYUN.MicroService.All.sln
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.W
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat.Work", "modules\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj", "{3E32DBDA-1C63-42B4-85D1-E84BBD072D89}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nexus", "nexus", "{87CE2F0B-0469-4C76-B325-00EA7AB94B99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BlobStoring.Nexus", "modules\nexus\LINGYUN.Abp.BlobStoring.Nexus\LINGYUN.Abp.BlobStoring.Nexus.csproj", "{34987F45-8234-428C-AB41-783D42295C32}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BlobStoring.Nexus.Tests", "tests\LINGYUN.Abp.BlobStoring.Nexus.Tests\LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj", "{227DA969-291B-4749-985C-7A83523B7F53}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.OssManagement.Nexus", "modules\nexus\LINGYUN.Abp.OssManagement.Nexus\LINGYUN.Abp.OssManagement.Nexus.csproj", "{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Sonatype.Nexus", "modules\nexus\LINGYUN.Abp.Sonatype.Nexus\LINGYUN.Abp.Sonatype.Nexus.csproj", "{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.OssManagement.Nexus.Tests", "tests\LINGYUN.Abp.OssManagement.Nexus.Tests\LINGYUN.Abp.OssManagement.Nexus.Tests.csproj", "{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1718,6 +1730,26 @@ Global
{3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E32DBDA-1C63-42B4-85D1-E84BBD072D89}.Release|Any CPU.Build.0 = Release|Any CPU
{34987F45-8234-428C-AB41-783D42295C32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34987F45-8234-428C-AB41-783D42295C32}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34987F45-8234-428C-AB41-783D42295C32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34987F45-8234-428C-AB41-783D42295C32}.Release|Any CPU.Build.0 = Release|Any CPU
{227DA969-291B-4749-985C-7A83523B7F53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{227DA969-291B-4749-985C-7A83523B7F53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{227DA969-291B-4749-985C-7A83523B7F53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{227DA969-291B-4749-985C-7A83523B7F53}.Release|Any CPU.Build.0 = Release|Any CPU
{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973}.Release|Any CPU.Build.0 = Release|Any CPU
{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C}.Release|Any CPU.Build.0 = Release|Any CPU
{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2041,6 +2073,12 @@ Global
{2C86306D-D626-41F8-BA3C-5C9B4123CE7D} = {83E698F6-F8CD-4604-AB80-01A203389501}
{2DC43D15-F20F-44EC-B3A3-47BD8BBB50CA} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21}
{3E32DBDA-1C63-42B4-85D1-E84BBD072D89} = {DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21}
{87CE2F0B-0469-4C76-B325-00EA7AB94B99} = {C5CAD011-DF84-4914-939C-0C029DCEF26F}
{34987F45-8234-428C-AB41-783D42295C32} = {87CE2F0B-0469-4C76-B325-00EA7AB94B99}
{227DA969-291B-4749-985C-7A83523B7F53} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
{A35E90D3-5375-4BFF-B6E2-24A8CDCBF973} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}
{CDE35EAE-4B48-40D2-BF57-68EFC5B5A97C} = {87CE2F0B-0469-4C76-B325-00EA7AB94B99}
{F197F8BB-87E3-43FC-92E7-DE8E60EB22E9} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
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>
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,20 @@
<Project Sdk="Microsoft.NET.Sdk">

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<Description>Oss对象存储Nexus集成</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Volo.Abp.BlobStoring" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Sonatype.Nexus\LINGYUN.Abp.Sonatype.Nexus.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using LINGYUN.Abp.Sonatype.Nexus;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;

namespace LINGYUN.Abp.BlobStoring.Nexus;

[DependsOn(
typeof(AbpBlobStoringModule),
typeof(AbpSonatypeNexusModule))]
public class AbpBlobStoringNexusModule : AbpModule
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;

namespace LINGYUN.Abp.BlobStoring.Nexus;
public class DefaultBlobRawPathCalculator : IBlobRawPathCalculator, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }

public DefaultBlobRawPathCalculator(
ICurrentTenant currentTenant,
IBlobContainerConfigurationProvider configurationProvider)
{
CurrentTenant = currentTenant;
ConfigurationProvider = configurationProvider;
}

public string CalculateGroup(string containerName, string blobName)
{
var blobPath = CalculateBasePath(containerName);

var lastFolderIndex = blobName.LastIndexOf("/");
if (lastFolderIndex > 0)
{
blobPath = blobPath.EnsureEndsWith('/');
blobPath += blobName.Substring(0, lastFolderIndex);
}

return blobPath.EnsureStartsWith('/').RemovePostFix("/");
}

public string CalculateName(string containerName, string blobName, bool replacePath = false)
{
var blobPath = CalculateBasePath(containerName);
blobPath = blobPath.EnsureEndsWith('/');
blobPath += blobName;

if (replacePath)
{
return blobName.Replace(blobPath.RemovePreFix("/"), "").RemovePreFix("/");
}

return blobPath.RemovePreFix("/");
}

protected virtual string CalculateBasePath(string containerName)
{
var configuration = ConfigurationProvider.Get<DefaultContainer>();
var nexusConfiguration = configuration.GetNexusConfiguration();
var blobPath = nexusConfiguration.BasePath;

if (CurrentTenant.Id == null)
{
blobPath = $"{blobPath}/host";
}
else
{
blobPath = $"{blobPath}/tenants/{CurrentTenant.Id.Value.ToString("D")}";
}

if (nexusConfiguration.AppendContainerNameToBasePath)
{
blobPath = $"{blobPath}/{containerName.RemovePreFix("/")}";
}

return blobPath.EnsureStartsWith('/');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Volo.Abp.BlobStoring;

namespace LINGYUN.Abp.BlobStoring.Nexus;
public interface IBlobRawPathCalculator
{
string CalculateGroup(string containerName, string blobName);

string CalculateName(string containerName, string blobName, bool replacePath = false);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using Volo.Abp.BlobStoring;

namespace LINGYUN.Abp.BlobStoring.Nexus
{
public static class NexusBlobContainerConfigurationExtensions
{
public static NexusBlobProviderConfiguration GetNexusConfiguration(
this BlobContainerConfiguration containerConfiguration)
{
return new NexusBlobProviderConfiguration(containerConfiguration);
}

public static BlobContainerConfiguration UseNexus(
this BlobContainerConfiguration containerConfiguration,
Action<NexusBlobProviderConfiguration> nexusConfigureAction)
{
containerConfiguration.ProviderType = typeof(NexusBlobProvider);
containerConfiguration.NamingNormalizers.TryAdd<NexusBlobNamingNormalizer>();

nexusConfigureAction(new NexusBlobProviderConfiguration(containerConfiguration));

return containerConfiguration;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;

namespace LINGYUN.Abp.BlobStoring.Nexus;
public class NexusBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency
{
public virtual string NormalizeContainerName(string containerName)
{
return Normalize(containerName);
}

public virtual string NormalizeBlobName(string blobName)
{
return Normalize(blobName);
}

protected virtual string Normalize(string fileName)
{
return fileName.Replace("\\", "/").Replace("//", "/");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Components;
using LINGYUN.Abp.Sonatype.Nexus.Search;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;

namespace LINGYUN.Abp.BlobStoring.Nexus;
public class NexusBlobProvider : BlobProviderBase, ITransientDependency
{
protected INexusAssetManager NexusAssetManager { get; }
protected INexusComponentManager NexusComponentManager { get; }
protected INexusLookupService NexusLookupService { get; }
protected IBlobRawPathCalculator BlobDirectoryCalculator { get; }

public NexusBlobProvider(
INexusAssetManager nexusAssetManager,
INexusComponentManager nexusComponentManager,
INexusLookupService nexusLookupService,
IBlobRawPathCalculator blobDirectoryCalculator)
{
NexusAssetManager = nexusAssetManager;
NexusComponentManager = nexusComponentManager;
NexusLookupService = nexusLookupService;
BlobDirectoryCalculator = blobDirectoryCalculator;
}

public async override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
var nexusComponent = await GetNexusomponentOrNull(args);
if (nexusComponent == null)
{
return false;
}
return await NexusComponentManager.DeleteAsync(nexusComponent.Id, args.CancellationToken);
}

public async override Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
var nexusAsset = await GetNexusAssetOrNull(args);
return nexusAsset != null;
}

public async override Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
var nexusAsset = await GetNexusAssetOrNull(args);
if (nexusAsset == null)
{
return null;
}

return await NexusAssetManager.GetContentOrNullAsync(nexusAsset);
}

public async override Task SaveAsync(BlobProviderSaveArgs args)
{
var nexusAsset = await GetNexusAssetOrNull(args);
if (!args.OverrideExisting && nexusAsset != null)
{
throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
}

var fileBytes = await args.BlobStream.GetAllBytesAsync();
var blobPath = BlobDirectoryCalculator.CalculateGroup(args.ContainerName, args.BlobName);
var blobName = BlobDirectoryCalculator.CalculateName(args.ContainerName, args.BlobName, true);
// blobName = blobName.Replace(blobPath.RemovePreFix("/"), "").RemovePreFix("/");
var asset1 = new Asset(blobName, fileBytes);

var nexusConfiguration = args.Configuration.GetNexusConfiguration();
var repository = nexusConfiguration.Repository;

var nexusRawBlobUploadArgs = new NexusRawBlobUploadArgs(
repository,
blobPath,
asset1);

await NexusComponentManager.UploadAsync(nexusRawBlobUploadArgs, args.CancellationToken);
}

protected async virtual Task<NexusAsset> GetNexusAssetOrNull(BlobProviderArgs args)
{
var nexusConfiguration = args.Configuration.GetNexusConfiguration();
var blobPath = BlobDirectoryCalculator.CalculateGroup(args.ContainerName, args.BlobName);
var blobName = BlobDirectoryCalculator.CalculateName(args.ContainerName, args.BlobName);
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
blobName);

var nexusAssetListResult = await NexusLookupService.ListAssetAsync(nexusSearchArgs, args.CancellationToken);
var nexusAsset = nexusAssetListResult.Items.FirstOrDefault();

return nexusAsset;
}

protected async virtual Task<NexusComponent> GetNexusomponentOrNull(BlobProviderArgs args)
{
var nexusConfiguration = args.Configuration.GetNexusConfiguration();
var blobPath = BlobDirectoryCalculator.CalculateGroup(args.ContainerName, args.BlobName);
var blobName = BlobDirectoryCalculator.CalculateName(args.ContainerName, args.BlobName);
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
blobName);

var nexusComponentResult = await NexusLookupService.ListComponentAsync(nexusSearchArgs, args.CancellationToken);
var nexusComponent = nexusComponentResult.Items.FirstOrDefault();

return nexusComponent;
}
}
Loading

0 comments on commit ad2176e

Please sign in to comment.