Browse Source

Merge pull request #890 from colinin/integration-sonatype-nexus

feat(oss): add Sonatype Nexus integration.
pull/914/head
yx lin 2 years ago
committed by GitHub
parent
commit
f04badea87
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 3
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/FodyWeavers.xml
  3. 30
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/FodyWeavers.xsd
  4. 20
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN.Abp.BlobStoring.Nexus.csproj
  5. 12
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusModule.cs
  6. 70
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/DefaultBlobRawPathCalculator.cs
  7. 9
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/IBlobRawPathCalculator.cs
  8. 26
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobContainerConfigurationExtensions.cs
  9. 21
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobNamingNormalizer.cs
  10. 114
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProvider.cs
  11. 28
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProviderConfiguration.cs
  12. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProviderConfigurationNames.cs
  13. 3
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/FodyWeavers.xml
  14. 30
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/FodyWeavers.xsd
  15. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN.Abp.OssManagement.Nexus.csproj
  16. 23
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusModule.cs
  17. 333
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs
  18. 49
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainerFactory.cs
  19. 25
      aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/System/IO/SystemExtensions.cs
  20. 3
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/FodyWeavers.xml
  21. 30
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/FodyWeavers.xsd
  22. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN.Abp.Sonatype.Nexus.csproj
  23. 28
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/AbpSonatypeNexusModule.cs
  24. 13
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/AbpSonatypeNexusOptions.cs
  25. 26
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/INexusAssetManager.cs
  26. 34
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAsset.cs
  27. 15
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAssetListResult.cs
  28. 98
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAssetManager.cs
  29. 11
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/Asset.cs
  30. 25
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/INexusComponentManager.cs
  31. 36
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponent.cs
  32. 20
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentListResult.cs
  33. 107
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentManager.cs
  34. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentUploadArgs.cs
  35. 80
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusRawBlobUploadArgs.cs
  36. 45
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/INexusRepositoryManager.cs
  37. 14
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepository.cs
  38. 14
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryCreateArgs.cs
  39. 29
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryListResult.cs
  40. 14
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryUpdateArgs.cs
  41. 9
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/INexusRawRepositoryManager.cs
  42. 9
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/NexusRawRepository.cs
  43. 17
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/RawGroup.cs
  44. 17
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/RawStorage.cs
  45. 13
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/INexusLookupService.cs
  46. 97
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/NexusLookupService.cs
  47. 29
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/NexusSearchArgs.cs
  48. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAsset.cs
  49. 54
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetData.cs
  50. 13
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetRead.cs
  51. 14
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetResult.cs
  52. 16
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowse.cs
  53. 29
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseComponent.cs
  54. 20
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseComponentResult.cs
  55. 19
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseNode.cs
  56. 10
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseReadComponent.cs
  57. 35
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUIRequest.cs
  58. 23
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUIResponse.cs
  59. 55
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUiServiceProxy.cs
  60. 9
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/ICoreUiServiceProxy.cs
  61. 5
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/INexusServiceProxy.cs
  62. 5
      aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/SonatypeNexusConsts.cs
  63. 2
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/GlobalUsings.cs
  64. 27
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj
  65. 6
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusTestBase.cs
  66. 41
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusTestModule.cs
  67. 11
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobContainer_Tests.cs
  68. 160
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs
  69. 6
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer1.cs
  70. 7
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer2.cs
  71. 6
      aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer3.cs
  72. 1
      aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/GlobalUsings.cs
  73. 27
      aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN.Abp.OssManagement.Nexus.Tests.csproj
  74. 6
      aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusTestsBase.cs
  75. 12
      aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusTestsModule.cs
  76. 44
      aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainerFactoryTests.cs

38
aspnet-core/LINGYUN.MicroService.All.sln

@ -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
@ -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
@ -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}

3
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/FodyWeavers.xsd

@ -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>

20
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN.Abp.BlobStoring.Nexus.csproj

@ -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>

12
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusModule.cs

@ -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
{
}

70
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/DefaultBlobRawPathCalculator.cs

@ -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('/');
}
}

9
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/IBlobRawPathCalculator.cs

@ -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);
}

26
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobContainerConfigurationExtensions.cs

@ -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;
}
}
}

21
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobNamingNormalizer.cs

@ -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("//", "/");
}
}

114
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProvider.cs

@ -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;
}
}

28
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProviderConfiguration.cs

@ -0,0 +1,28 @@
using Volo.Abp;
using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Nexus;
public class NexusBlobProviderConfiguration
{
public string BasePath {
get => _containerConfiguration.GetConfiguration<string>(NexusBlobProviderConfigurationNames.BasePath);
set => _containerConfiguration.SetConfiguration(NexusBlobProviderConfigurationNames.BasePath, value);
}
public bool AppendContainerNameToBasePath {
get => _containerConfiguration.GetConfigurationOrDefault(NexusBlobProviderConfigurationNames.AppendContainerNameToBasePath, true);
set => _containerConfiguration.SetConfiguration(NexusBlobProviderConfigurationNames.AppendContainerNameToBasePath, value);
}
public string Repository {
get => _containerConfiguration.GetConfiguration<string>(NexusBlobProviderConfigurationNames.Repository);
set => _containerConfiguration.SetConfiguration(NexusBlobProviderConfigurationNames.Repository, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
private readonly BlobContainerConfiguration _containerConfiguration;
public NexusBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
{
_containerConfiguration = containerConfiguration;
}
}

16
aspnet-core/modules/nexus/LINGYUN.Abp.BlobStoring.Nexus/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobProviderConfigurationNames.cs

@ -0,0 +1,16 @@
namespace LINGYUN.Abp.BlobStoring.Nexus;
public static class NexusBlobProviderConfigurationNames
{
/// <summary>
/// 基础路径
/// </summary>
public const string BasePath = "Sonatype:Nexus:Raw:BasePath";
/// <summary>
/// 添加容器名称到基础路径
/// </summary>
public const string AppendContainerNameToBasePath = "Sonatype:Nexus:Raw:AppendContainerNameToBasePath";
/// <summary>
/// Nexus raw仓库名称
/// </summary>
public const string Repository = "Sonatype:Nexus:Raw:Repository";
}

3
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>

30
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/FodyWeavers.xsd

@ -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>

16
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN.Abp.OssManagement.Nexus.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.BlobStoring.Nexus\LINGYUN.Abp.BlobStoring.Nexus.csproj" />
<ProjectReference Include="..\..\oss-management\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj" />
</ItemGroup>
</Project>

23
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusModule.cs

@ -0,0 +1,23 @@
using LINGYUN.Abp.BlobStoring.Nexus;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.Nexus;
[DependsOn(
typeof(AbpBlobStoringNexusModule),
typeof(AbpOssManagementDomainModule))]
public class AbpOssManagementNexusModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<IOssContainerFactory, NexusOssContainerFactory>();
context.Services.AddTransient<IOssObjectExpireor>(provider =>
provider
.GetRequiredService<IOssContainerFactory>()
.Create()
.As<NexusOssContainer>());
}
}

333
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs

@ -0,0 +1,333 @@
using LINGYUN.Abp.BlobStoring.Nexus;
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Components;
using LINGYUN.Abp.Sonatype.Nexus.Search;
using LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
using LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.BlobStoring;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.Nexus;
internal class NexusOssContainer : IOssContainer, IOssObjectExpireor
{
protected ICoreUiServiceProxy CoreUiServiceProxy { get; }
protected INexusAssetManager NexusAssetManager { get; }
protected INexusComponentManager NexusComponentManager { get; }
protected INexusLookupService NexusLookupService { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IBlobRawPathCalculator BlobRawPathCalculator { get; }
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
public NexusOssContainer(
ICoreUiServiceProxy coreUiServiceProxy,
INexusAssetManager nexusAssetManager,
INexusComponentManager nexusComponentManager,
INexusLookupService nexusLookupService,
ICurrentTenant currentTenant,
IBlobRawPathCalculator blobRawPathCalculator,
IBlobContainerConfigurationProvider configurationProvider)
{
CoreUiServiceProxy = coreUiServiceProxy;
NexusAssetManager = nexusAssetManager;
NexusComponentManager = nexusComponentManager;
NexusLookupService = nexusLookupService;
CurrentTenant = currentTenant;
BlobRawPathCalculator = blobRawPathCalculator;
ConfigurationProvider = configurationProvider;
}
public Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
{
throw new NotImplementedException();
}
public async virtual Task<OssContainer> CreateAsync(string name)
{
// 创建容器的逻辑就是创建一个包含一个空白assets的component
var blobPath = BlobRawPathCalculator.CalculateGroup(name, "readme");
var nexusConfiguration = GetNexusConfiguration();
var uploadArgs = new NexusRawBlobUploadArgs(
nexusConfiguration.Repository,
blobPath,
new Asset("readme", Encoding.UTF8.GetBytes("A placeholder for an empty container.")));
await NexusComponentManager.UploadAsync(uploadArgs);
return new OssContainer(
name,
DateTime.Now,
0L,
DateTime.Now);
}
public async virtual Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = GetBasePath(request.Bucket, request.Path, request.Object);
if (!request.Overwrite)
{
var searchBlobName = GetObjectName(request.Bucket, request.Path, request.Object);
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
searchBlobName);
var nexusAssetListResult = await NexusLookupService.ListAssetAsync(nexusSearchArgs);
if (nexusAssetListResult.Items.Any())
{
throw new BusinessException(code: OssManagementErrorCodes.ObjectAlreadyExists);
}
}
var blobName = GetObjectName(request.Bucket, request.Path, request.Object, true);
var blobBytes = await request.Content.GetAllBytesAsync();
var uploadArgs = new NexusRawBlobUploadArgs(
nexusConfiguration.Repository,
blobPath,
new Asset(blobName, blobBytes));
await NexusComponentManager.UploadAsync(uploadArgs);
var getOssObjectRequest = new GetOssObjectRequest(
request.Bucket, request.Object, request.Path);
return await GetObjectAsync(getOssObjectRequest);
}
public async virtual Task DeleteAsync(string name)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = BlobRawPathCalculator.CalculateGroup(name, "/");
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
"/");
var nexusComponentListResult = await NexusLookupService.ListComponentAsync(nexusSearchArgs);
var nexusComponent = nexusComponentListResult.Items.FirstOrDefault();
if (nexusComponent != null)
{
await NexusComponentManager.DeleteAsync(nexusComponent.Id);
}
}
public async virtual Task DeleteObjectAsync(GetOssObjectRequest request)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = GetBasePath(request.Bucket, request.Path, request.Object);
var blobName = GetObjectName(request.Bucket, request.Path, request.Object);
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
blobName);
var nexusAssetListResult = await NexusLookupService.ListAssetAsync(nexusSearchArgs);
var nexusAsset = nexusAssetListResult.Items.FirstOrDefault();
if (nexusAsset != null)
{
await NexusAssetManager.DeleteAsync(nexusAsset.Id);
}
}
public virtual Task<bool> ExistsAsync(string name)
{
throw new NotImplementedException();
}
public Task ExpireAsync(ExprieOssObjectRequest request)
{
throw new NotImplementedException();
}
public async virtual Task<OssContainer> GetAsync(string name)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = BlobRawPathCalculator.CalculateGroup(name, "/");
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
"/");
var nexusComponentListResult = await NexusLookupService.ListComponentAsync(nexusSearchArgs);
var nexusComponent = nexusComponentListResult.Items.FirstOrDefault();
if (nexusComponent == null)
{
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound);
}
var lastModified = nexusComponent.Assets
.OrderBy(asset => asset.LastModified)
.Select(asset => asset.LastModified)
.FirstOrDefault();
return new OssContainer(
nexusComponent.Name,
lastModified ?? new DateTime(),
0L,
lastModified);
}
public async virtual Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = request.Prefix.RemovePreFix(".").RemovePreFix("/");
var readComponent = CoreUIBrowse.Read(nexusConfiguration.Repository, blobPath);
var coreUIResponse = await CoreUiServiceProxy.SearchAsync<CoreUIBrowseReadComponent, CoreUIBrowseComponentResult>(readComponent);
var ifFolderComponents = coreUIResponse.Result.Data.Where(component => component.Type == "folder").ToArray();
return new GetOssContainersResponse(
request.Prefix,
request.Marker,
"",
ifFolderComponents.Length,
ifFolderComponents.Select(component =>
new OssContainer(
component.Text,
new DateTime(),
0L,
null,
new Dictionary<string, string>()))
.ToList());
}
public async virtual Task<OssObject> GetObjectAsync(GetOssObjectRequest request)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = GetBasePath(request.Bucket, request.Path, request.Object);
var blobFullName = GetObjectName(request.Bucket, request.Path, request.Object);
var blobName = GetObjectName(request.Bucket, request.Path, request.Object, true);
var nexusSearchArgs = new NexusSearchArgs(
nexusConfiguration.Repository,
blobPath,
blobFullName);
var nexusAssetListResult = await NexusLookupService.ListAssetAsync(nexusSearchArgs);
var nexusAssetItem = nexusAssetListResult.Items.FirstOrDefault();
if (nexusAssetItem == null)
{
throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound);
}
var (Repository, ComponentId) = DecodeBase64Id(nexusAssetItem.Id);
var readAsset = CoreUIAsset.Read(ComponentId, Repository);
var coreUIResponse = await CoreUiServiceProxy.SearchAsync<CoreUIAssetRead, CoreUIAssetResult>(readAsset);
var checksum = coreUIResponse.Result.Data.Attributes.GetOrDefault("checksum");
var metadata = new Dictionary<string, string>();
if (checksum != null)
{
foreach (var data in checksum)
{
metadata.Add(data.Key, data.Value.ToString());
}
}
return new OssObject(
blobName,
blobPath,
checksum?.GetOrDefault("md5")?.ToString(),
coreUIResponse.Result.Data.BlobCreated,
coreUIResponse.Result.Data.Size,
coreUIResponse.Result.Data.BlobUpdated,
metadata
);
}
public async virtual Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request)
{
var nexusConfiguration = GetNexusConfiguration();
var blobPath = GetBasePath(request.BucketName, request.Prefix, "");
var readComponent = CoreUIBrowse.Read(nexusConfiguration.Repository, blobPath.RemovePreFix("/"));
var coreUIResponse = await CoreUiServiceProxy.SearchAsync<CoreUIBrowseReadComponent, CoreUIBrowseComponentResult>(readComponent);
var filterComponents = coreUIResponse.Result.Data
.WhereIf(string.Equals(request.Delimiter, "/"), component => component.Type == "folder")
.OrderBy(component => component.Text)
.AsQueryable()
.PageBy(request.Current, request.MaxKeys ?? 10)
.ToArray();
var response = new GetOssObjectsResponse(
request.BucketName,
request.Prefix,
request.Marker,
"",
"/", // 文件系统目录分隔符
coreUIResponse.Result.Data.Count,
filterComponents.Select(component => new OssObject(
component.Text,
request.Prefix,
"",
null,
0L,
null,
new Dictionary<string, string>(),
component.Type == "folder")
{
FullName = component.Id
})
.ToList());
return response;
}
protected virtual NexusBlobProviderConfiguration GetNexusConfiguration()
{
var configuration = ConfigurationProvider.Get<AbpOssManagementContainer>();
var nexusConfiguration = configuration.GetNexusConfiguration();
return nexusConfiguration;
}
protected virtual string GetBasePath(string bucket, string path, string @object)
{
var objectPath = bucket.EnsureEndsWith('/') + (!path.IsNullOrWhiteSpace() ? path.RemovePreFix("/") : "");
objectPath = BlobRawPathCalculator.CalculateGroup(objectPath, @object);
return objectPath;
}
protected virtual string GetObjectName(string bucket, string path, string @object, bool replaceObjectPath = false)
{
var objectPath = bucket.EnsureEndsWith('/') + (!path.IsNullOrWhiteSpace() ? path.RemovePreFix("/") : "");
//objectPath = BlobRawPathCalculator.CalculateGroup(objectPath, @object);
var objectName = BlobRawPathCalculator.CalculateName(objectPath, @object, replaceObjectPath);
return objectName;
}
protected virtual (string Repository, string ComponentId) DecodeBase64Id(string base64id)
{
base64id = base64id.Replace("-", "+").Replace("_", "/");
var base64 = Encoding.ASCII.GetBytes(base64id);
var padding = base64.Length * 3 % 4;//(base64.Length*6 % 8)/2
if (padding != 0)
{
base64id = base64id.PadRight(base64id.Length + padding, '=');
}
var buffer = Convert.FromBase64String(base64id);
var decoded = Encoding.UTF8.GetString(buffer);
var parts = decoded.Split(":");
if (parts.Length != 2)
{
throw new AbpException("Unable to parse component id " + decoded);
}
return (parts[0], parts[1]);
}
}

49
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainerFactory.cs

@ -0,0 +1,49 @@
using LINGYUN.Abp.BlobStoring.Nexus;
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Components;
using LINGYUN.Abp.Sonatype.Nexus.Search;
using LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
using Volo.Abp.BlobStoring;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.Nexus;
internal class NexusOssContainerFactory : IOssContainerFactory
{
protected ICoreUiServiceProxy CoreUiServiceProxy { get; }
protected INexusAssetManager NexusAssetManager { get; }
protected INexusComponentManager NexusComponentManager { get; }
protected INexusLookupService NexusLookupService { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IBlobRawPathCalculator BlobRawPathCalculator { get; }
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
public NexusOssContainerFactory(
ICoreUiServiceProxy coreUiServiceProxy,
INexusAssetManager nexusAssetManager,
INexusComponentManager nexusComponentManager,
INexusLookupService nexusLookupService,
ICurrentTenant currentTenant,
IBlobRawPathCalculator blobRawPathCalculator,
IBlobContainerConfigurationProvider configurationProvider)
{
CoreUiServiceProxy = coreUiServiceProxy;
NexusAssetManager = nexusAssetManager;
NexusComponentManager = nexusComponentManager;
NexusLookupService = nexusLookupService;
CurrentTenant = currentTenant;
BlobRawPathCalculator = blobRawPathCalculator;
ConfigurationProvider = configurationProvider;
}
public IOssContainer Create()
{
return new NexusOssContainer(
CoreUiServiceProxy,
NexusAssetManager,
NexusComponentManager,
NexusLookupService,
CurrentTenant,
BlobRawPathCalculator,
ConfigurationProvider);
}
}

25
aspnet-core/modules/nexus/LINGYUN.Abp.OssManagement.Nexus/System/IO/SystemExtensions.cs

@ -0,0 +1,25 @@
using System.Security.Cryptography;
using System.Text;
namespace System.IO
{
internal static class SystemExtensions
{
public static string MD5(this Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(0, SeekOrigin.Begin);
}
using MD5 md5 = new MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(stream);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
stream.Seek(0, SeekOrigin.Begin);
return sb.ToString();
}
}
}

3
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/FodyWeavers.xsd

@ -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>

16
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN.Abp.Sonatype.Nexus.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Json" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Http" Version="$(MicrosoftPackageVersion)" />
</ItemGroup>
</Project>

28
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/AbpSonatypeNexusModule.cs

@ -0,0 +1,28 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using Volo.Abp.Json;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Sonatype.Nexus;
[DependsOn(
typeof(AbpJsonModule))]
public class AbpSonatypeNexusModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpSonatypeNexusOptions>(configuration.GetSection("Sonatype:Nexus"));
context.Services.AddHttpClient(
SonatypeNexusConsts.ApiClient,
(serviceProvider, client) =>
{
var options = serviceProvider.GetRequiredService<IOptions<AbpSonatypeNexusOptions>>().Value;
client.BaseAddress = new Uri(options.BaseUrl);
client.DefaultRequestHeaders.Add("X-Nexus-Ui", "true");
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
});
}
}

13
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/AbpSonatypeNexusOptions.cs

@ -0,0 +1,13 @@
namespace LINGYUN.Abp.Sonatype.Nexus;
public class AbpSonatypeNexusOptions
{
public string BaseUrl { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public AbpSonatypeNexusOptions()
{
BaseUrl = "http://127.0.0.1:8081";
UserName = "sonatype";
Password = "sonatype";
}
}

26
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/INexusAssetManager.cs

@ -0,0 +1,26 @@
using JetBrains.Annotations;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Sonatype.Nexus.Assets;
public interface INexusAssetManager
{
Task<NexusAssetListResult> ListAsync(
[NotNull] string repository,
string continuationToken = null,
CancellationToken cancellationToken = default);
Task<NexusAsset> GetAsync(
[NotNull] string id,
CancellationToken cancellationToken = default);
Task DeleteAsync(
[NotNull] string id,
CancellationToken cancellationToken = default);
Task<Stream> GetContentOrNullAsync(
[NotNull] NexusAsset asset,
CancellationToken cancellationToken = default);
}

34
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAsset.cs

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Assets;
public class NexusAsset
{
[JsonPropertyName("downloadUrl")]
public string DownloadUrl { get; set; }
[JsonPropertyName("path")]
public string Path { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("repository")]
public string Repository { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("contentType")]
public string ContentType { get; set; }
[JsonPropertyName("lastModified")]
public DateTime? LastModified { get; set; }
[JsonPropertyName("blobCreated")]
public DateTime? BlobCreated { get; set; }
[JsonPropertyName("checksum")]
public Dictionary<string, string> Checksum { get; set; }
}

15
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAssetListResult.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Assets;
[Serializable]
public class NexusAssetListResult
{
[JsonPropertyName("continuationToken")]
public string ContinuationToken { get; set; }
[JsonPropertyName("items")]
public List<NexusAsset> Items { get; set; }
}

98
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Assets/NexusAssetManager.cs

@ -0,0 +1,98 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.Sonatype.Nexus.Assets;
public class NexusAssetManager : INexusAssetManager, ISingletonDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected AbpSonatypeNexusOptions Options { get; }
public NexusAssetManager(
IJsonSerializer jsonSerializer,
IHttpClientFactory httpClientFactory,
IOptions<AbpSonatypeNexusOptions> options)
{
Options = options.Value;
JsonSerializer = jsonSerializer;
HttpClientFactory = httpClientFactory;
}
public async virtual Task DeleteAsync([NotNull] string id, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var username = Options.UserName;
var password = Options.Password;
var authBase64Data = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
var requestMessage = new HttpRequestMessage(HttpMethod.Delete, $"/service/rest/v1/assets/{id}");
requestMessage.Headers.Add("Authorization", $"Basic {authBase64Data}");
var response = await client.SendAsync(requestMessage, cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
}
public async virtual Task<NexusAsset> GetAsync([NotNull] string id, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var response = await client.GetAsync($"/service/rest/v1/assets/{id}", cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusAsset = JsonSerializer.Deserialize<NexusAsset>(responseContent);
return nexusAsset;
}
public async virtual Task<Stream> GetContentOrNullAsync([NotNull] NexusAsset asset, CancellationToken cancellationToken = default)
{
if (asset == null || asset.DownloadUrl.IsNullOrWhiteSpace())
{
return null;
}
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
return await client.GetStreamAsync(asset.DownloadUrl);
}
public async virtual Task<NexusAssetListResult> ListAsync([NotNull] string repository, string continuationToken = null, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var urlBuilder = new StringBuilder();
urlBuilder.Append("/service/rest/v1/assets");
urlBuilder.AppendFormat("?repository={0}", repository);
if (!continuationToken.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&continuationToken={0}", continuationToken);
}
var response = await client.GetAsync(urlBuilder.ToString(), cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusAssetListResult = JsonSerializer.Deserialize<NexusAssetListResult>(responseContent);
return nexusAssetListResult;
}
}

11
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/Asset.cs

@ -0,0 +1,11 @@
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
public class Asset
{
public string FileName { get; }
public byte[] FileBytes { get; }
public Asset(string fileName, byte[] fileBytes)
{
FileName = fileName;
FileBytes = fileBytes;
}
}

25
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/INexusComponentManager.cs

@ -0,0 +1,25 @@
using JetBrains.Annotations;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
public interface INexusComponentManager
{
Task<NexusComponentListResult> ListAsync(
[NotNull] string repository,
string continuationToken = null,
CancellationToken cancellationToken = default);
Task<NexusComponent> GetAsync(
[NotNull] string id,
CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(
[NotNull] string id,
CancellationToken cancellationToken = default);
Task UploadAsync(
[NotNull] NexusComponentUploadArgs args,
CancellationToken cancellationToken = default);
}

36
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponent.cs

@ -0,0 +1,36 @@
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
[Serializable]
public class NexusComponent
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("repository")]
public string Repository { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("group")]
public string Group { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("version")]
public string Version { get; set; }
[JsonPropertyName("assets")]
public List<NexusAsset> Assets { get; set; }
public NexusComponent()
{
Assets = new List<NexusAsset>();
}
}

20
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentListResult.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
[Serializable]
public class NexusComponentListResult
{
[JsonPropertyName("continuationToken")]
public string ContinuationToken { get; set; }
[JsonPropertyName("items")]
public List<NexusComponent> Items { get; set; }
public NexusComponentListResult()
{
Items = new List<NexusComponent>();
}
}

107
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentManager.cs

@ -0,0 +1,107 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
public class NexusComponentManager : INexusComponentManager, ISingletonDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected AbpSonatypeNexusOptions Options { get; }
public NexusComponentManager(
IJsonSerializer jsonSerializer,
IHttpClientFactory httpClientFactory,
IOptions<AbpSonatypeNexusOptions> options)
{
Options = options.Value;
JsonSerializer = jsonSerializer;
HttpClientFactory = httpClientFactory;
}
public async virtual Task UploadAsync([NotNull] NexusComponentUploadArgs args, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var username = Options.UserName;
var password = Options.Password;
var authBase64Data = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
using var formDataContent = args.BuildContent();
var requestMessage = new HttpRequestMessage(
HttpMethod.Post,
$"/service/rest/v1/components?repository={args.Repository}")
{
Content = formDataContent,
};
requestMessage.Headers.Add("Authorization", $"Basic {authBase64Data}");
var response = await client.SendAsync(requestMessage, cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
}
public async virtual Task<bool> DeleteAsync([NotNull] string id, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var username = Options.UserName;
var password = Options.Password;
var authBase64Data = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
var requestMessage = new HttpRequestMessage(HttpMethod.Delete, $"/service/rest/v1/components/{id}");
requestMessage.Headers.Add("Authorization", $"Basic {authBase64Data}");
var response = await client.SendAsync(requestMessage, cancellationToken);
return response.IsSuccessStatusCode;
}
public async virtual Task<NexusComponent> GetAsync([NotNull] string id, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var response = await client.GetAsync($"/service/rest/v1/components/{id}", cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusComponent = JsonSerializer.Deserialize<NexusComponent>(responseContent);
return nexusComponent;
}
public async virtual Task<NexusComponentListResult> ListAsync([NotNull] string repository, string continuationToken = null, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var urlBuilder = new StringBuilder();
urlBuilder.Append("/service/rest/v1/components");
urlBuilder.AppendFormat("?repository={0}", repository);
if (!continuationToken.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&continuationToken={0}", continuationToken);
}
var response = await client.GetAsync(urlBuilder.ToString(), cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusComponentListResult = JsonSerializer.Deserialize<NexusComponentListResult>(responseContent);
return nexusComponentListResult;
}
}

16
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusComponentUploadArgs.cs

@ -0,0 +1,16 @@
using System.Net.Http;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
public abstract class NexusComponentUploadArgs
{
public string Repository { get; }
public string Directory { get; }
protected NexusComponentUploadArgs(string repository, string directory)
{
Repository = repository;
Directory = directory;
}
public abstract HttpContent BuildContent();
}

80
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Components/NexusRawBlobUploadArgs.cs

@ -0,0 +1,80 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
namespace LINGYUN.Abp.Sonatype.Nexus.Components;
public class NexusRawBlobUploadArgs : NexusComponentUploadArgs
{
public Asset Asset1 { get; }
public Asset Asset2 { get; }
public Asset Asset3 { get; }
public NexusRawBlobUploadArgs(
string repository,
string directory,
Asset asset1,
Asset asset2 = null,
Asset asset3 = null)
: base(repository, directory)
{
Asset1 = asset1;
Asset2 = asset2;
Asset3 = asset3;
}
public override HttpContent BuildContent()
{
var boundary = "--BOUNDARY--" + DateTimeOffset.Now.Ticks.ToString("x");
var formDataContent = new MultipartFormDataContent(boundary);
formDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse($"multipart/form-data; boundary={boundary}");
var rawDirectory = new StringContent(Directory);
rawDirectory.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.directory");
if (Asset1 != null)
{
var rawAsset1 = new ByteArrayContent(Asset1.FileBytes);
rawAsset1.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset1");
rawAsset1.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
rawAsset1.Headers.ContentLength = Asset1.FileBytes.Length;
var rawAsset1FileName = new StringContent(Asset1.FileName);
rawAsset1FileName.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset1.filename");
formDataContent.Add(rawAsset1);
formDataContent.Add(rawAsset1FileName);
}
if (Asset2 != null)
{
var rawAsset2 = new ByteArrayContent(Asset2.FileBytes);
rawAsset2.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset2");
rawAsset2.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
rawAsset2.Headers.ContentLength = Asset2.FileBytes.Length;
var rawAsset2FileName = new StringContent(Asset2.FileName);
rawAsset2FileName.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset2.filename");
formDataContent.Add(rawAsset2);
formDataContent.Add(rawAsset2FileName);
}
if (Asset3 != null)
{
var rawAsset3 = new ByteArrayContent(Asset2.FileBytes);
rawAsset3.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset3");
rawAsset3.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
rawAsset3.Headers.ContentLength = Asset2.FileBytes.Length;
var rawAsset3FileName = new StringContent(Asset2.FileName);
rawAsset3FileName.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse($"form-data; name=raw.asset3.filename");
formDataContent.Add(rawAsset3);
formDataContent.Add(rawAsset3FileName);
}
formDataContent.Add(rawDirectory);
return formDataContent;
}
}

45
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/INexusRepositoryManager.cs

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories;
public interface INexusRepositoryManager<TRepository, TRepositoryCreateArgs, TRepositoryUpdateArgs>
where TRepository : NexusRepository
where TRepositoryCreateArgs : NexusRepositoryCreateArgs
where TRepositoryUpdateArgs: NexusRepositoryUpdateArgs
{
Task CreateAsync(TRepositoryCreateArgs args, CancellationToken cancellationToken = default);
Task<TRepository> GetAsync(string name, CancellationToken cancellationToken = default);
Task UpdateAsync(string name, TRepositoryUpdateArgs args, CancellationToken cancellationToken = default);
Task DeleteAsync(string name, CancellationToken cancellationToken = default);
Task<List<NexusRepositoryListResult>> ListAsync(CancellationToken cancellationToken = default);
}
public interface INexusRepositoryManager<TRepository, TRepositoryCreateArgs>
where TRepository : NexusRepository
where TRepositoryCreateArgs : NexusRepositoryCreateArgs
{
Task CreateAsync(TRepositoryCreateArgs args, CancellationToken cancellationToken = default);
Task<TRepository> GetAsync(string name, CancellationToken cancellationToken = default);
Task DeleteAsync(string name, CancellationToken cancellationToken = default);
Task<List<NexusRepositoryListResult>> ListAsync(CancellationToken cancellationToken = default);
}
public interface INexusRepositoryManager<TRepository>
where TRepository : NexusRepository
{
Task<TRepository> GetAsync(string name, CancellationToken cancellationToken = default);
Task DeleteAsync(string name, CancellationToken cancellationToken = default);
Task<List<NexusRepositoryListResult>> ListAsync(CancellationToken cancellationToken = default);
}

14
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepository.cs

@ -0,0 +1,14 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories;
[Serializable]
public abstract class NexusRepository
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("online")]
public bool Online { get; set; }
}

14
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryCreateArgs.cs

@ -0,0 +1,14 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories;
[Serializable]
public abstract class NexusRepositoryCreateArgs
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("online")]
public bool Online { get; set; }
}

29
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryListResult.cs

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories;
[Serializable]
public class NexusRepositoryListResult
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("url")]
public string Url { get; set; }
[JsonPropertyName("attributes")]
public Dictionary<string, object> Attributes { get; set; }
public NexusRepositoryListResult()
{
Attributes = new Dictionary<string, object>();
}
}

14
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/NexusRepositoryUpdateArgs.cs

@ -0,0 +1,14 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories;
[Serializable]
public abstract class NexusRepositoryUpdateArgs
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("online")]
public bool Online { get; set; }
}

9
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/INexusRawRepositoryManager.cs

@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories.Raw;
public interface INexusRawRepositoryManager
{
}

9
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/NexusRawRepository.cs

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories.Raw;
public class NexusRawRepository : NexusRepository
{
[JsonPropertyName("storage")]
public RawStorage Storage { get; set; }
}

17
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/RawGroup.cs

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories.Raw;
[Serializable]
public class RawGroup
{
[JsonPropertyName("memberNames")]
public List<string> MemberNames { get; set; }
public RawGroup()
{
MemberNames = new List<string>();
}
}

17
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Repositories/Raw/RawStorage.cs

@ -0,0 +1,17 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Repositories.Raw;
[Serializable]
public class RawStorage
{
[JsonPropertyName("blobStoreName")]
public string BlobStoreName { get; set; }
[JsonPropertyName("strictContentTypeValidation")]
public bool StrictContentTypeValidation { get; set; }
[JsonPropertyName("RawGroup")]
public RawGroup Group { get; set; }
}

13
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/INexusLookupService.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Components;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Sonatype.Nexus.Search;
public interface INexusLookupService
{
Task<NexusComponentListResult> ListComponentAsync(NexusSearchArgs args, CancellationToken cancellationToken = default);
Task<NexusAssetListResult> ListAssetAsync(NexusSearchArgs args, CancellationToken cancellationToken = default);
}

97
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/NexusLookupService.cs

@ -0,0 +1,97 @@
using LINGYUN.Abp.Sonatype.Nexus.Assets;
using LINGYUN.Abp.Sonatype.Nexus.Components;
using Microsoft.Extensions.Options;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.Sonatype.Nexus.Search;
public class NexusLookupService : INexusLookupService, ISingletonDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected AbpSonatypeNexusOptions Options { get; }
public NexusLookupService(
IJsonSerializer jsonSerializer,
IHttpClientFactory httpClientFactory,
IOptions<AbpSonatypeNexusOptions> options)
{
Options = options.Value;
JsonSerializer = jsonSerializer;
HttpClientFactory = httpClientFactory;
}
public async virtual Task<NexusAssetListResult> ListAssetAsync(NexusSearchArgs args, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var urlBuilder = new StringBuilder();
urlBuilder.AppendFormat("/service/rest/v1/search/assets?format={0}", args.Format);
urlBuilder.AppendFormat("&repository={0}", args.Repository);
urlBuilder.AppendFormat("&group={0}", args.Group);
urlBuilder.AppendFormat("&name={0}", args.Name);
if(!args.Keyword.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&q={0}", args.Keyword);
}
if (!args.Version.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&version={0}", args.Version);
}
if (args.Timeout.HasValue)
{
urlBuilder.AppendFormat("&timeout={0}", args.Timeout.Value);
}
var response = await client.GetAsync(urlBuilder.ToString(), cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusAssetListResult = JsonSerializer.Deserialize<NexusAssetListResult>(responseContent);
return nexusAssetListResult;
}
public async virtual Task<NexusComponentListResult> ListComponentAsync(NexusSearchArgs args, CancellationToken cancellationToken = default)
{
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
var urlBuilder = new StringBuilder();
urlBuilder.AppendFormat("/service/rest/v1/search?format={0}", args.Format);
urlBuilder.AppendFormat("&repository={0}", args.Repository);
urlBuilder.AppendFormat("&group={0}", args.Group);
urlBuilder.AppendFormat("&name={0}", args.Name);
if (!args.Keyword.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&q={0}", args.Keyword);
}
if (!args.Version.IsNullOrWhiteSpace())
{
urlBuilder.AppendFormat("&version={0}", args.Version);
}
if (args.Timeout.HasValue)
{
urlBuilder.AppendFormat("&timeout={0}", args.Timeout.Value);
}
var response = await client.GetAsync(urlBuilder.ToString(), cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var nexusComponentListResult = JsonSerializer.Deserialize<NexusComponentListResult>(responseContent);
return nexusComponentListResult;
}
}

29
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Search/NexusSearchArgs.cs

@ -0,0 +1,29 @@
namespace LINGYUN.Abp.Sonatype.Nexus.Search;
public class NexusSearchArgs
{
public string Keyword { get; }
public string Repository { get; }
public string Group { get; }
public string Name { get; }
public string Format { get; set; } = "raw";
public int? Timeout { get; set; }
public string Version { get; }
public NexusSearchArgs(
string repository,
string group,
string name,
string format = "raw",
string keyword = null,
string version = null,
int? timeout = null)
{
Keyword = keyword;
Repository = repository;
Group = group;
Name = name;
Format = format;
Timeout = timeout;
Version = version;
}
}

16
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAsset.cs

@ -0,0 +1,16 @@
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Assets;
public static class CoreUIAsset
{
public static CoreUIRequest<CoreUIAssetRead> Read(
string assetId,
string repository)
{
var asset = new CoreUIAssetRead(assetId, repository);
return new CoreUIRequest<CoreUIAssetRead>(
"coreui_Component",
"readAsset",
asset);
}
}

54
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetData.cs

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Assets;
[Serializable]
public class CoreUIAssetData
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("format")]
public string Format { get; set; }
[JsonPropertyName("contentType")]
public string ContentType { get; set; }
[JsonPropertyName("blobUpdated")]
public DateTime? BlobUpdated { get; set; }
[JsonPropertyName("blobCreated")]
public DateTime? BlobCreated { get; set; }
[JsonPropertyName("createdBy")]
public string CreatedBy { get; set; }
[JsonPropertyName("createdByIp")]
public string CreatedByIp { get; set; }
[JsonPropertyName("blobRef")]
public string BlobRef { get; set; }
[JsonPropertyName("componentId")]
public string ComponentId { get; set; }
[JsonPropertyName("lastDownloaded")]
public string LastDownloaded { get; set; }
[JsonPropertyName("containingRepositoryName")]
public string ContainingRepositoryName { get; set; }
[JsonPropertyName("repositoryName")]
public string RepositoryName { get; set; }
[JsonPropertyName("size")]
public long Size { get; set; }
[JsonPropertyName("attributes")]
public Dictionary<string, Dictionary<string, object>> Attributes { get; set; }
}

13
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetRead.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Assets;
public class CoreUIAssetRead : List<string>
{
public CoreUIAssetRead(
string assetId,
string repository)
{
Add(assetId);
Add(repository);
}
}

14
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Assets/CoreUIAssetResult.cs

@ -0,0 +1,14 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Assets;
[Serializable]
public class CoreUIAssetResult
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("data")]
public CoreUIAssetData Data { get; set; }
}

16
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowse.cs

@ -0,0 +1,16 @@
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
public static class CoreUIBrowse
{
public static CoreUIRequest<CoreUIBrowseReadComponent> Read(
string repository,
string node = "/")
{
var readComponent = new CoreUIBrowseReadComponent(repository, node);
return new CoreUIRequest<CoreUIBrowseReadComponent>(
"coreui_Browse",
"read",
readComponent);
}
}

29
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseComponent.cs

@ -0,0 +1,29 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
[Serializable]
public class CoreUIBrowseComponent
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("assetId")]
public string AssetId { get; set; }
[JsonPropertyName("componentId")]
public string ComponentId { get; set; }
[JsonPropertyName("packageUrl")]
public string PackageUrl { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("leaf")]
public bool Leaf { get; set; }
}

20
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseComponentResult.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
[Serializable]
public class CoreUIBrowseComponentResult
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("data")]
public List<CoreUIBrowseComponent> Data { get; set; }
public CoreUIBrowseComponentResult()
{
Data = new List<CoreUIBrowseComponent>();
}
}

19
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseNode.cs

@ -0,0 +1,19 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
[Serializable]
public class CoreUIBrowseNode
{
[JsonPropertyName("node")]
public string Node { get; set; }
[JsonPropertyName("repositoryName")]
public string RepositoryName { get; set; }
public CoreUIBrowseNode(string repositoryName, string node = "/")
{
Node = node;
RepositoryName = repositoryName;
}
}

10
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/Browsers/CoreUIBrowseReadComponent.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI.Browsers;
public class CoreUIBrowseReadComponent : List<CoreUIBrowseNode>
{
public CoreUIBrowseReadComponent(string repository, string node = "/")
{
Add(new CoreUIBrowseNode(repository, node));
}
}

35
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUIRequest.cs

@ -0,0 +1,35 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
[Serializable]
public class CoreUIRequest<TData>
{
[JsonPropertyName("action")]
public string Action { get; set; }
[JsonPropertyName("method")]
public string Method { get; set; }
[JsonPropertyName("tid")]
public long Tid { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public TData Data { get; set; }
public CoreUIRequest(
string action,
string method,
TData data,
string type = "rpc")
{
Action = action;
Method = method;
Type = type;
Data = data;
}
}

23
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUIResponse.cs

@ -0,0 +1,23 @@
using System;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
[Serializable]
public class CoreUIResponse<TResult>
{
[JsonPropertyName("action")]
public string Action { get; set; }
[JsonPropertyName("method")]
public string Method { get; set; }
[JsonPropertyName("tid")]
public long Tid { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("result")]
public TResult Result { get; set; }
}

55
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/CoreUiServiceProxy.cs

@ -0,0 +1,55 @@
using Microsoft.Extensions.Options;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
public class CoreUiServiceProxy : ICoreUiServiceProxy, ISingletonDependency
{
private static int _idCurrent = 1;
protected IJsonSerializer JsonSerializer { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected AbpSonatypeNexusOptions Options { get; }
public CoreUiServiceProxy(
IJsonSerializer jsonSerializer,
IHttpClientFactory httpClientFactory,
IOptions<AbpSonatypeNexusOptions> options)
{
Options = options.Value;
JsonSerializer = jsonSerializer;
HttpClientFactory = httpClientFactory;
}
public async virtual Task<CoreUIResponse<TResult>> SearchAsync<TData, TResult>(
CoreUIRequest<TData> request,
CancellationToken cancellationToken = default)
{
Interlocked.Increment(ref _idCurrent);
request.Tid = _idCurrent;
var client = HttpClientFactory.CreateClient(SonatypeNexusConsts.ApiClient);
using var requestContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/service/extdirect")
{
Content = requestContent,
};
var response = await client.SendAsync(requestMessage, cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new AbpException(response.ReasonPhrase);
}
var responseContent = await response.Content.ReadAsStringAsync();
var coreUiResponse = JsonSerializer.Deserialize<CoreUIResponse<TResult>>(responseContent);
return coreUiResponse;
}
}

9
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/CoreUI/ICoreUiServiceProxy.cs

@ -0,0 +1,9 @@
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Sonatype.Nexus.Services.CoreUI;
public interface ICoreUiServiceProxy : INexusServiceProxy
{
Task<CoreUIResponse<TResult>> SearchAsync<TData, TResult>(CoreUIRequest<TData> request, CancellationToken cancellationToken = default);
}

5
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/Services/INexusServiceProxy.cs

@ -0,0 +1,5 @@
namespace LINGYUN.Abp.Sonatype.Nexus.Services;
public interface INexusServiceProxy
{
}

5
aspnet-core/modules/nexus/LINGYUN.Abp.Sonatype.Nexus/LINGYUN/Abp/Sonatype/Nexus/SonatypeNexusConsts.cs

@ -0,0 +1,5 @@
namespace LINGYUN.Abp.Sonatype.Nexus;
internal static class SonatypeNexusConsts
{
public const string ApiClient = "Sonatype.Nexus";
}

2
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/GlobalUsings.cs

@ -0,0 +1,2 @@
global using Xunit;
global using Shouldly;

27
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace />
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitPackageVersion)">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="$(CoverletCollectorPackageVersion)">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\nexus\LINGYUN.Abp.BlobStoring.Nexus\LINGYUN.Abp.BlobStoring.Nexus.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" />
</ItemGroup>
</Project>

6
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusTestBase.cs

@ -0,0 +1,6 @@
using LINGYUN.Abp.Tests;
namespace LINGYUN.Abp.BlobStoring.Nexus;
public abstract class AbpBlobStoringNexusTestBase : AbpTestsBase<AbpBlobStoringNexusTestModule>
{
}

41
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/AbpBlobStoringNexusTestModule.cs

@ -0,0 +1,41 @@
using LINGYUN.Abp.Tests;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.BlobStoring.Nexus;
[DependsOn(
typeof(AbpBlobStoringNexusModule),
typeof(AbpTestsBaseModule))]
public class AbpBlobStoringNexusTestModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configurationOptions = new AbpConfigurationBuilderOptions
{
BasePath = @"D:\Projects\Development\Abp\BlobStoring\Nexus",
EnvironmentName = "Test"
};
context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions));
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseNexus(nexus =>
{
nexus.BasePath = configuration[NexusBlobProviderConfigurationNames.BasePath];
nexus.Repository = configuration[NexusBlobProviderConfigurationNames.Repository];
});
});
});
}
}

11
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN/Abp/BlobStoring/Nexus/NexusBlobContainer_Tests.cs

@ -0,0 +1,11 @@
using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Nexus;
public class NexusBlobContainer_Tests : BlobContainer_Tests<AbpBlobStoringNexusTestModule>
{
public NexusBlobContainer_Tests()
{
}
}

160
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs

@ -0,0 +1,160 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.BlobStoring.TestObjects;
using Volo.Abp.Clients;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Testing;
using Xunit;
namespace Volo.Abp.BlobStoring;
public abstract class BlobContainer_Tests<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{
protected IBlobContainer<TestContainer1> Container { get; }
protected ICurrentTenant CurrentTenant { get; }
protected BlobContainer_Tests()
{
Container = GetRequiredService<IBlobContainer<TestContainer1>>();
CurrentTenant = GetRequiredService<ICurrentTenant>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
[Theory]
[InlineData("Should_Save_And_Get_Blobs")]
[InlineData("Should_Save_And_Get_Blobs.txt")]
[InlineData("test-folder/Should_Save_And_Get_Blobs")]
public async Task Should_Save_And_Get_Blobs(string blobName)
{
var testContent = "test content".GetBytes();
await Container.SaveAsync(blobName, testContent);
await Task.Delay(3000);
var result = await Container.GetAllBytesAsync(blobName);
result.SequenceEqual(testContent).ShouldBeTrue();
await Container.DeleteAsync(blobName);
}
[Fact]
public async Task Should_Save_And_Get_Blobs_In_Different_Tenant()
{
var blobName = "Should_Save_And_Get_Blobs_In_Different_Tenant";
var testContent = "test content".GetBytes();
using (CurrentTenant.Change(Guid.NewGuid()))
{
await Container.SaveAsync(blobName, testContent);
await Task.Delay(2000);
(await Container.GetAllBytesAsync(blobName)).SequenceEqual(testContent).ShouldBeTrue();
await Container.DeleteAsync(blobName);
await Task.Delay(2000);
}
using (CurrentTenant.Change(Guid.NewGuid()))
{
await Container.SaveAsync(blobName, testContent);
await Task.Delay(2000);
(await Container.GetAllBytesAsync(blobName)).SequenceEqual(testContent).ShouldBeTrue();
using (CurrentTenant.Change(null))
{
// Could not found the requested BLOB...
await Assert.ThrowsAsync<AbpException>(async () =>
await Container.GetAllBytesAsync(blobName)
);
}
await Container.DeleteAsync(blobName);
await Task.Delay(2000);
}
using (CurrentTenant.Change(null))
{
await Container.SaveAsync(blobName, testContent);
await Task.Delay(2000);
(await Container.GetAllBytesAsync(blobName)).SequenceEqual(testContent).ShouldBeTrue();
await Container.DeleteAsync(blobName);
}
}
[Fact]
public async Task Should_Overwrite_Pre_Saved_Blob_If_Requested()
{
var blobName = "Should_Overwrite_Pre_Saved_Blob_If_Requested";
var testContent = "test content".GetBytes();
await Container.SaveAsync(blobName, testContent);
await Task.Delay(2000);
var testContentOverwritten = "test content overwritten".GetBytes();
await Container.SaveAsync(blobName, testContentOverwritten, true);
await Task.Delay(2000);
var result = await Container.GetAllBytesAsync(blobName);
result.SequenceEqual(testContentOverwritten).ShouldBeTrue();
await Container.DeleteAsync(blobName);
}
[Fact]
public async Task Should_Not_Allow_To_Overwrite_Pre_Saved_Blob_By_Default()
{
var blobName = "Should_Not_Allow_To_Overwrite_Pre_Saved_Blob_By_Default";
var testContent = "test content".GetBytes();
await Container.SaveAsync(blobName, testContent);
await Task.Delay(2000);
var testContentOverwritten = "test content overwritten".GetBytes();
await Assert.ThrowsAsync<BlobAlreadyExistsException>(() =>
Container.SaveAsync(blobName, testContentOverwritten)
);
await Container.DeleteAsync(blobName);
}
[Theory]
[InlineData("Should_Delete_Saved_Blobs")]
[InlineData("Should_Delete_Saved_Blobs.txt")]
[InlineData("test-folder/Should_Delete_Saved_Blobs")]
public async Task Should_Delete_Saved_Blobs(string blobName)
{
await Container.SaveAsync(blobName, "test content".GetBytes());
await Task.Delay(2000);
(await Container.GetAllBytesAsync(blobName)).ShouldNotBeNull();
await Container.DeleteAsync(blobName);
await Task.Delay(2000);
(await Container.GetAllBytesOrNullAsync(blobName)).ShouldBeNull();
}
[Theory]
[InlineData("Saved_Blobs_Should_Exists")]
[InlineData("Saved_Blobs_Should_Exists.txt")]
[InlineData("test-folder/Saved_Blobs_Should_Exists")]
public async Task Saved_Blobs_Should_Exists(string blobName)
{
await Container.SaveAsync(blobName, "test content".GetBytes());
await Task.Delay(2000);
(await Container.ExistsAsync(blobName)).ShouldBeTrue();
await Container.DeleteAsync(blobName);
await Task.Delay(2000);
(await Container.ExistsAsync(blobName)).ShouldBeFalse();
}
[Theory]
[InlineData("Unknown_Blobs_Should_Not_Exists")]
[InlineData("Unknown_Blobs_Should_Not_Exists.txt")]
[InlineData("test-folder/Unknown_Blobs_Should_Not_Exists")]
public async Task Unknown_Blobs_Should_Not_Exists(string blobName)
{
await Container.DeleteAsync(blobName);
await Task.Delay(2000);
(await Container.ExistsAsync(blobName)).ShouldBeFalse();
}
}

6
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer1.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.BlobStoring.TestObjects;
public class TestContainer1
{
}

7
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer2.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.BlobStoring.TestObjects;
[BlobContainerName("Test2")]
public class TestContainer2
{
}

6
aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/Volo/Abp/BlobStoring/TestObjects/TestContainer3.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.BlobStoring.TestObjects;
public class TestContainer3
{
}

1
aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/GlobalUsings.cs

@ -0,0 +1 @@
global using Xunit;

27
aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN.Abp.OssManagement.Nexus.Tests.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace />
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitPackageVersion)">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="$(CoverletCollectorPackageVersion)">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\nexus\LINGYUN.Abp.OssManagement.Nexus\LINGYUN.Abp.OssManagement.Nexus.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.BlobStoring.Nexus.Tests\LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj" />
</ItemGroup>
</Project>

6
aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusTestsBase.cs

@ -0,0 +1,6 @@
using LINGYUN.Abp.Tests;
namespace LINGYUN.Abp.OssManagement.Nexus;
public abstract class AbpOssManagementNexusTestsBase : AbpTestsBase<AbpOssManagementNexusTestsModule>
{
}

12
aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusTestsModule.cs

@ -0,0 +1,12 @@
using LINGYUN.Abp.BlobStoring.Nexus;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.Nexus;
[DependsOn(
typeof(AbpOssManagementNexusModule),
typeof(AbpBlobStoringNexusTestModule))]
public class AbpOssManagementNexusTestsModule : AbpModule
{
}

44
aspnet-core/tests/LINGYUN.Abp.OssManagement.Nexus.Tests/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainerFactoryTests.cs

@ -0,0 +1,44 @@
using Shouldly;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace LINGYUN.Abp.OssManagement.Nexus;
public class NexusOssContainerFactoryTests : AbpOssManagementNexusTestsBase
{
protected IOssContainerFactory OssContainerFactory { get; }
public NexusOssContainerFactoryTests()
{
OssContainerFactory = GetRequiredService<IOssContainerFactory>();
}
[Theory]
[InlineData("/test-repo")]
public async virtual Task CreateAsync(string containerName)
{
var ossContainer = OssContainerFactory.Create();
await ossContainer.CreateAsync(containerName);
}
[Theory]
[InlineData("/test-repo", "CreateObjectAsync", "/aaa/bbb/ccc")]
public async virtual Task CreateObjectAsync(string containerName, string objectName, string path = null)
{
var textBytes = Encoding.UTF8.GetBytes("CreateObjectAsync");
using var stream = new MemoryStream();
await stream.WriteAsync(textBytes, 0, textBytes.Length);
var ossContainer = OssContainerFactory.Create();
var createObjectRequest = new CreateOssObjectRequest(
containerName,
objectName,
stream,
path);
var oss = await ossContainer.CreateObjectAsync(createObjectRequest);
oss.ShouldNotBeNull();
}
}
Loading…
Cancel
Save