Browse Source

CmsKit - Fix merge conflict from dev to blogs-refactorings

pull/7845/head
enisn 6 years ago
parent
commit
fb8fcefb4c
  1. 2
      docs/en/Blob-Storing-Aliyun.md
  2. 2
      docs/en/Blob-Storing-Aws.md
  3. 2
      docs/en/Blob-Storing-Azure.md
  4. 2
      docs/zh-Hans/Blob-Storing-Aliyun.md
  5. 2
      docs/zh-Hans/Blob-Storing-Aws.md
  6. 2
      docs/zh-Hans/Blob-Storing-Azure.md
  7. 14
      framework/Volo.Abp.sln
  8. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs
  9. 27
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs
  10. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs
  11. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  12. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  13. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  14. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
  15. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  16. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  17. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs
  18. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
  19. 16
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs
  20. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs
  21. 26
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs
  22. 63
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs
  23. 5
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs
  24. 4
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs
  25. 22
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs
  26. 3
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xml
  27. 30
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xsd
  28. 24
      framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
  29. 11
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs
  30. 16
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs
  31. 43
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs
  32. 26
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj
  33. 12
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs
  34. 18
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs
  35. 37
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs
  36. 11
      framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json
  37. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs
  38. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs
  39. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs
  40. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs
  41. 69
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs
  42. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs
  43. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs
  44. 28
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs
  45. 39
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs
  46. 3
      modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Tags/TagAppService.cs
  47. 5
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  48. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  49. 24
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs
  50. 44
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogManager.cs
  51. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs
  52. 22
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogSlugAlreadyExistException.cs
  53. 21
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs
  54. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs
  55. 4
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptorCheck.cs
  56. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs
  57. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs
  58. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs
  59. 30
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs
  60. 24
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs
  61. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs
  62. 33
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs
  63. 4
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagRepository.cs
  64. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs
  65. 8
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitions.cs
  66. 51
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs
  67. 46
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs
  68. 16
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs
  69. 56
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs
  70. 16
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs
  71. 92
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogAdminAppService_Tests.cs
  72. 10
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs
  73. 50
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/BlogManager_Test.cs
  74. 54
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs
  75. 28
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs
  76. 27
      modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs
  77. 45
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs
  78. 2
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs
  79. 2
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  80. 20
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSecurityStampValidator.cs
  81. 77
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs
  82. 11
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs
  83. 35
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/PasswordOptionsExtensions.cs
  84. 1
      nupkg/common.ps1

2
docs/en/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy"; aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date"; aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name"; aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false; aliyun.CreateContainerIfNotExists = true;
}); });
}); });
}); });

2
docs/en/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy"; Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date"; Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name"; Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false; Aws.CreateContainerIfNotExists = true;
}); });
}); });
}); });

2
docs/en/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{ {
azure.ConnectionString = "your azure connection string"; azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name"; azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false; azure.CreateContainerIfNotExists = true;
}); });
}); });
}); });

2
docs/zh-Hans/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy"; aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date"; aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name"; aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false; aliyun.CreateContainerIfNotExists = true;
}); });
}); });
}); });

2
docs/zh-Hans/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy"; Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date"; Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name"; Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false; Aws.CreateContainerIfNotExists = true;
}); });
}); });
}); });

2
docs/zh-Hans/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{ {
azure.ConnectionString = "your azure connection string"; azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name"; azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false; azure.CreateContainerIfNotExists = true;
}); });
}); });
}); });

14
framework/Volo.Abp.sln

@ -361,6 +361,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Tests", "test
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Abstractions", "src\Volo.Abp.EventBus.Abstractions\Volo.Abp.EventBus.Abstractions.csproj", "{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Abstractions", "src\Volo.Abp.EventBus.Abstractions\Volo.Abp.EventBus.Abstractions.csproj", "{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun", "src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj", "{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun.Tests", "test\Volo.Abp.Sms.Aliyun.Tests\Volo.Abp.Sms.Aliyun.Tests.csproj", "{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1075,6 +1079,14 @@ Global
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.Build.0 = Release|Any CPU {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.Build.0 = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.Build.0 = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1257,6 +1269,8 @@ Global
{00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA} {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs

@ -271,6 +271,7 @@ namespace Volo.Abp.AspNetCore.Mvc
actionModel.AddParameter(ParameterApiDescriptionModel.Create( actionModel.AddParameter(ParameterApiDescriptionModel.Create(
parameterDescription.Name, parameterDescription.Name,
_options.ApiParameterNameGenerator?.Invoke(parameterDescription),
matchedMethodParamName, matchedMethodParamName,
parameterDescription.Type, parameterDescription.Type,
parameterDescription.RouteInfo?.IsOptional ?? false, parameterDescription.RouteInfo?.IsOptional ?? false,

27
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs

@ -2,6 +2,9 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.Conventions;
@ -13,6 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public Func<MethodInfo, string> ActionNameGenerator { get; set; } public Func<MethodInfo, string> ActionNameGenerator { get; set; }
public Func<ApiParameterDescription, string> ApiParameterNameGenerator { get; set; }
public AspNetCoreApiDescriptionModelProviderOptions() public AspNetCoreApiDescriptionModelProviderOptions()
{ {
ControllerNameGenerator = (controllerType, setting) => ControllerNameGenerator = (controllerType, setting) =>
@ -52,6 +57,28 @@ namespace Volo.Abp.AspNetCore.Mvc
return methodNameBuilder.ToString(); return methodNameBuilder.ToString();
}; };
ApiParameterNameGenerator = (apiParameterDescription) =>
{
if (apiParameterDescription.ModelMetadata is DefaultModelMetadata defaultModelMetadata)
{
var jsonPropertyNameAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is System.Text.Json.Serialization.JsonPropertyNameAttribute);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = (Newtonsoft.Json.JsonPropertyAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is Newtonsoft.Json.JsonPropertyAttribute);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
}
return null;
};
} }
} }
} }

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -50,7 +50,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return; return;
} }
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options)) using (var uow = unitOfWorkManager.Begin(options))
{ {
var result = await next(); var result = await next();
@ -58,6 +57,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{ {
await uow.CompleteAsync(context.HttpContext.RequestAborted); await uow.CompleteAsync(context.HttpContext.RequestAborted);
} }
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
} }
} }

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -55,7 +55,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return; return;
} }
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options)) using (var uow = unitOfWorkManager.Begin(options))
{ {
var result = await next(); var result = await next();
@ -63,6 +62,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{ {
await uow.CompleteAsync(context.HttpContext.RequestAborted); await uow.CompleteAsync(context.HttpContext.RequestAborted);
} }
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
} }
} }

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -147,19 +147,34 @@ namespace Volo.Abp.Cli.Commands
} }
var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs); var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
if (!createSolutionFolder)
{
Logger.LogInformation("Create Solution Folder: no");
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long); var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
var outputFolderRoot = var outputFolderRoot =
outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(); outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
outputFolder = createSolutionFolder ? SolutionName solutionName;
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) : if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
outputFolderRoot; {
var microserviceSolutionName = FindMicroserviceSolutionName(outputFolderRoot);
if (microserviceSolutionName == null)
{
throw new CliUsageException("This command should be run inside a folder that contains a microservice solution!");
}
solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
outputFolder = MicroserviceServiceTemplateBase.CalculateTargetFolder(outputFolderRoot, projectName);
uiFramework = uiFramework == UiFramework.NotSpecified ? FindMicroserviceSolutionUiFramework(outputFolderRoot) : uiFramework;
}
else
{
solutionName = SolutionName.Parse(projectName);
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
}
Volo.Abp.IO.DirectoryHelper.CreateIfNotExists(outputFolder); Volo.Abp.IO.DirectoryHelper.CreateIfNotExists(outputFolder);
@ -176,7 +191,7 @@ namespace Volo.Abp.Cli.Commands
var result = await TemplateProjectBuilder.BuildAsync( var result = await TemplateProjectBuilder.BuildAsync(
new ProjectBuildArgs( new ProjectBuildArgs(
SolutionName.Parse(projectName), solutionName,
template, template,
version, version,
databaseProvider, databaseProvider,
@ -245,6 +260,32 @@ namespace Volo.Abp.Cli.Commands
} }
} }
private string FindMicroserviceSolutionName(string outputFolderRoot)
{
var slnFile = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
if (slnFile == null)
{
return null;
}
return Path.GetFileName(slnFile).RemovePostFix(".sln");
}
private UiFramework FindMicroserviceSolutionUiFramework(string outputFolderRoot)
{
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "blazor")))
{
return UiFramework.Blazor;
}
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "web")))
{
return UiFramework.Mvc;
}
return UiFramework.None;
}
private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial) private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
{ {
uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework; uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
@ -383,6 +424,11 @@ namespace Volo.Abp.Cli.Commands
protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs) protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs)
{ {
if (commandLineArgs.Options.ContainsKey("no-ui"))
{
return UiFramework.None;
}
var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long); var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
switch (optionValue) switch (optionValue)
{ {

30
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files; using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
@ -25,7 +26,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var localVoloRepoPath = context.BuildArgs.VoloGitHubLocalRepositoryPath; var localVoloRepoPath = context.BuildArgs.VoloGitHubLocalRepositoryPath;
new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer( new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer(
context.Files, context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName", context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
localAbpRepoPath, localAbpRepoPath,
localVoloRepoPath localVoloRepoPath
@ -41,7 +42,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
} }
new ProjectReferenceReplacer.NugetReferenceReplacer( new ProjectReferenceReplacer.NugetReferenceReplacer(
context.Files, context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName", context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
nugetPackageVersion nugetPackageVersion
).Run(); ).Run();
@ -70,13 +71,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private abstract class ProjectReferenceReplacer private abstract class ProjectReferenceReplacer
{ {
private readonly List<FileEntry> _entries; private readonly List<FileEntry> _entries;
private readonly bool _isMicroserviceServiceTemplate;
private readonly string _projectName; private readonly string _projectName;
protected ProjectReferenceReplacer( protected ProjectReferenceReplacer(
List<FileEntry> entries, ProjectBuildContext context,
string projectName) string projectName)
{ {
_entries = entries; _entries = context.Files;
_isMicroserviceServiceTemplate = MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.Template?.Name);
_projectName = projectName; _projectName = projectName;
} }
@ -113,14 +116,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var oldNodeIncludeValue = oldNode.Attributes["Include"].Value; var oldNodeIncludeValue = oldNode.Attributes["Include"].Value;
// ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method // ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method
if (oldNodeIncludeValue.Contains(_projectName) && _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue)))) if (oldNodeIncludeValue.Contains(_projectName))
{ {
continue; if (_isMicroserviceServiceTemplate || _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue))))
{
continue;
}
} }
XmlNode newNode = null; XmlNode newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
oldNode.ParentNode.ReplaceChild(newNode, oldNode); oldNode.ParentNode.ReplaceChild(newNode, oldNode);
} }
@ -145,8 +149,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{ {
private readonly string _nugetPackageVersion; private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string projectName, string nugetPackageVersion) public NugetReferenceReplacer(ProjectBuildContext context, string projectName, string nugetPackageVersion)
: base(entries, projectName) : base(context, projectName)
{ {
_nugetPackageVersion = nugetPackageVersion; _nugetPackageVersion = nugetPackageVersion;
} }
@ -183,8 +187,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private readonly string _gitHubAbpLocalRepositoryPath; private readonly string _gitHubAbpLocalRepositoryPath;
private readonly string _gitHubVoloLocalRepositoryPath; private readonly string _gitHubVoloLocalRepositoryPath;
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath) public LocalProjectPathReferenceReplacer(ProjectBuildContext context, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(entries, projectName) : base(context, projectName)
{ {
_gitHubAbpLocalRepositoryPath = gitHubAbpLocalRepositoryPath; _gitHubAbpLocalRepositoryPath = gitHubAbpLocalRepositoryPath;
_gitHubVoloLocalRepositoryPath = gitHubVoloLocalRepositoryPath; _gitHubVoloLocalRepositoryPath = gitHubVoloLocalRepositoryPath;

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -85,11 +85,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context) private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context)
{ {
if (_solutionFilePath == null) if (_solutionFilePath == null)
{ {
_solutionFilePath = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name ?? _solutionFilePath = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name; context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.sln")?.Name;
} }
if (_projectFolderPath == null) if (_projectFolderPath == null)
{ {

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Cli.ProjectBuilding.Files; using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{ {
@ -8,13 +9,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{ {
public override void Execute(ProjectBuildContext context) public override void Execute(ProjectBuildContext context)
{ {
new SolutionRenamer( if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.BuildArgs.TemplateName))
context.Files, {
"MyCompanyName", new SolutionRenamer(
"MyProjectName", context.Files,
context.BuildArgs.SolutionName.CompanyName, "MyCompanyName.MyProjectName",
context.BuildArgs.SolutionName.ProjectName "MicroserviceName",
).Run(); context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
else
{
new SolutionRenamer(
context.Files,
"MyCompanyName",
"MyProjectName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
} }
private class SolutionRenamer private class SolutionRenamer

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -33,7 +33,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
} }
if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor) if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor)
&& context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName) && context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName
&& context.Template.Name != MicroserviceServiceProTemplate.TemplateName)
{ {
pipeline.Steps.Add(new RemoveRootFolderStep()); pipeline.Steps.Add(new RemoveRootFolderStep());
} }

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs

@ -17,6 +17,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
ProjectName = projectName; ProjectName = projectName;
} }
public static SolutionName Parse(string fullName, string microserviceName)
{
return new SolutionName(fullName + "." + microserviceName, fullName, microserviceName);
}
public static SolutionName Parse(string fullName) public static SolutionName Parse(string fullName)
{ {
if (fullName.Length < 1) if (fullName.Length < 1)
@ -47,4 +52,4 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new SolutionName(fullName, companyName, projectName); return new SolutionName(fullName, companyName, projectName);
} }
} }
} }

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs

@ -28,7 +28,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider, public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler, IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
AuthService authService, AuthService authService,
CliHttpClientFactory cliHttpClientFactory) CliHttpClientFactory cliHttpClientFactory)
{ {
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
@ -56,6 +56,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new AppProTemplate(); return new AppProTemplate();
case MicroserviceProTemplate.TemplateName: case MicroserviceProTemplate.TemplateName:
return new MicroserviceProTemplate(); return new MicroserviceProTemplate();
case MicroserviceServiceProTemplate.TemplateName:
return new MicroserviceServiceProTemplate();
case ModuleTemplate.TemplateName: case ModuleTemplate.TemplateName:
return new ModuleTemplate(); return new ModuleTemplate();
case ModuleProTemplate.TemplateName: case ModuleProTemplate.TemplateName:

16
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs

@ -0,0 +1,16 @@
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public class MicroserviceServiceProTemplate : MicroserviceServiceTemplateBase
{
/// <summary>
/// "microservice-service-pro".
/// </summary>
public const string TemplateName = "microservice-service-pro";
public MicroserviceServiceProTemplate()
: base(TemplateName)
{
DocumentUrl = null; // todo: set this
}
}
}

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public abstract class MicroserviceServiceTemplateBase : TemplateInfo
{
protected MicroserviceServiceTemplateBase([NotNull] string name)
: base(name)
{
}
public static bool IsMicroserviceServiceTemplate(string templateName)
{
return templateName == MicroserviceServiceProTemplate.TemplateName;
}
public static string CalculateTargetFolder(string mainSolutionFolder, string serviceName)
{
serviceName = serviceName.ToCamelCase().RemovePostFix("Service");
return Path.Combine(mainSolutionFolder, "microservices", serviceName);
}
public override IEnumerable<ProjectBuildPipelineStep> GetCustomSteps(ProjectBuildContext context)
{
var steps = new List<ProjectBuildPipelineStep>();
DeleteUnrelatedUiProject(context, steps);
RandomizeStringEncryption(context, steps);
return steps;
}
private static void DeleteUnrelatedUiProject(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
switch (context.BuildArgs.UiFramework)
{
case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
break;
default:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
}
}
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new RandomizeStringEncryptionStep());
}
}
}

26
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs

@ -33,27 +33,41 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
switch (context.BuildArgs.UiFramework) switch (context.BuildArgs.UiFramework)
{ {
case UiFramework.None: case UiFramework.None:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); "/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular")); steps.Add(new RemoveFolderStep("/angular"));
break; break;
case UiFramework.Angular: case UiFramework.Angular:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); "/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
break; break;
case UiFramework.Blazor: case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveFolderStep("/angular")); steps.Add(new RemoveFolderStep("/angular"));
break; break;
case UiFramework.Mvc: case UiFramework.Mvc:
case UiFramework.NotSpecified: case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular")); steps.Add(new RemoveFolderStep("/angular"));
break; break;
} }
steps.Add(new RemoveFolderStep("/microservices/template"));
} }
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps) private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

63
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs

@ -34,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification
} }
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects); await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectToAngularJsonAsync(angularPath, projects); await AddProjectToAngularJsonAsync(angularPath, projects);
} }
catch (Exception e) catch (Exception e)
@ -93,6 +94,61 @@ namespace Volo.Abp.Cli.ProjectModification
File.WriteAllText(angularJsonFilePath, json.ToString(Formatting.Indented)); File.WriteAllText(angularJsonFilePath, json.ToString(Formatting.Indented));
} }
private async Task AddScriptsToPackageJsonAsync(string angularPath)
{
var packageJsonFilePath = Path.Combine(angularPath, "package.json");
var fileContent = File.ReadAllText(packageJsonFilePath);
var json = JObject.Parse(fileContent);
var scriptsJobject = (JObject) json["scripts"];
if (scriptsJobject == null || scriptsJobject["postinstall"] != null || scriptsJobject["compile:ivy"] != null)
{
return;
}
scriptsJobject["postinstall"] = "npm run compile:ivy";
scriptsJobject["compile:ivy"] = "yarn ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json' --source node_modules";
File.WriteAllText(packageJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task CreateTsConfigProdJsonAsync(string angularPath)
{
var tsConfigProdJsonFilePath = Path.Combine(angularPath, "tsconfig.prod.json");
if (File.Exists(tsConfigProdJsonFilePath))
{
return;
}
var json = new JObject(
new JProperty("compileOnSave", false),
new JProperty("compilerOptions", new JObject(
new JProperty("baseUrl", "./"),
new JProperty("outDir", "./dist/out-tsc"),
new JProperty("sourceMap", true),
new JProperty("declaration", false),
new JProperty("downlevelIteration", true),
new JProperty("experimentalDecorators", true),
new JProperty("module", "esnext"),
new JProperty("moduleResolution", "node"),
new JProperty("importHelpers", true),
new JProperty("target", "es2015"),
new JProperty("typeRoots", new JArray(new JValue("node_modules/@types"))),
new JProperty("lib", new JArray(new JValue("es2018"), new JValue("dom"))),
new JProperty("types", new JArray(new JValue("jest")))
)),
new JProperty("angularCompilerOptions", new JObject(
new JProperty("fullTemplateTypeCheck", true),
new JProperty("strictInjectionParameters", true)
))
);
File.WriteAllText(tsConfigProdJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task AddPathsToTsConfigAsync(string angularPath, string angularProjectsPath, private async Task AddPathsToTsConfigAsync(string angularPath, string angularProjectsPath,
List<string> projects) List<string> projects)
{ {
@ -105,7 +161,8 @@ namespace Volo.Abp.Cli.ProjectModification
{ {
var projectPackageName = await GetProjectPackageNameAsync(angularProjectsPath, project); var projectPackageName = await GetProjectPackageNameAsync(angularProjectsPath, project);
var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts", SearchOption.AllDirectories) var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts",
SearchOption.AllDirectories)
.Where(p => !p.Contains("\\node_modules\\")) .Where(p => !p.Contains("\\node_modules\\"))
.Select(p => p.RemovePreFix(angularPath).Replace("\\", "/").RemovePreFix("/")); .Select(p => p.RemovePreFix(angularPath).Replace("\\", "/").RemovePreFix("/"));
@ -171,8 +228,10 @@ namespace Volo.Abp.Cli.ProjectModification
{ {
continue; continue;
} }
Directory.Move(folderUnderProject, Path.Combine(folder, Path.GetFileName(folderUnderProject))); Directory.Move(folderUnderProject, Path.Combine(folder, Path.GetFileName(folderUnderProject)));
} }
projectsInFolder = Directory.GetDirectories(folder); projectsInFolder = Directory.GetDirectories(folder);
} }

5
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs

@ -10,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
public string Name { get; set; } public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; } public string Type { get; set; }
public string TypeSimple { get; set; } public string TypeSimple { get; set; }
@ -29,11 +31,12 @@ namespace Volo.Abp.Http.Modeling
} }
public static ParameterApiDescriptionModel Create(string name, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null) public static ParameterApiDescriptionModel Create(string name, string jsonName, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null)
{ {
return new ParameterApiDescriptionModel return new ParameterApiDescriptionModel
{ {
Name = name, Name = name,
JsonName = jsonName,
NameOnMethod = nameOnMethod, NameOnMethod = nameOnMethod,
Type = type != null ? TypeHelper.GetFullNameHandlingNullableAndGenerics(type) : null, Type = type != null ? TypeHelper.GetFullNameHandlingNullableAndGenerics(type) : null,
TypeSimple = type != null ? ApiTypeNameHelper.GetSimpleTypeName(type) : null, TypeSimple = type != null ? ApiTypeNameHelper.GetSimpleTypeName(type) : null,

4
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs

@ -1,6 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Reflection; using System.Reflection;
using Volo.Abp.Http.ProxyScripting.Configuration;
namespace Volo.Abp.Http.Modeling namespace Volo.Abp.Http.Modeling
{ {
@ -9,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
{ {
public string Name { get; set; } public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; } public string Type { get; set; }
public string TypeSimple { get; set; } public string TypeSimple { get; set; }
@ -21,6 +24,7 @@ namespace Volo.Abp.Http.Modeling
return new PropertyApiDescriptionModel return new PropertyApiDescriptionModel
{ {
Name = propertyInfo.Name, Name = propertyInfo.Name,
JsonName = AbpApiProxyScriptingOptions.PropertyNameGenerator.Invoke(propertyInfo),
Type = ApiTypeNameHelper.GetTypeName(propertyInfo.PropertyType), Type = ApiTypeNameHelper.GetTypeName(propertyInfo.PropertyType),
TypeSimple = ApiTypeNameHelper.GetSimpleTypeName(propertyInfo.PropertyType), TypeSimple = ApiTypeNameHelper.GetSimpleTypeName(propertyInfo.PropertyType),
IsRequired = propertyInfo.IsDefined(typeof(RequiredAttribute), true) IsRequired = propertyInfo.IsDefined(typeof(RequiredAttribute), true)

22
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.Http.ProxyScripting.Configuration namespace Volo.Abp.Http.ProxyScripting.Configuration
{ {
@ -7,9 +8,30 @@ namespace Volo.Abp.Http.ProxyScripting.Configuration
{ {
public IDictionary<string, Type> Generators { get; } public IDictionary<string, Type> Generators { get; }
public static Func<PropertyInfo, string> PropertyNameGenerator { get; set; }
public AbpApiProxyScriptingOptions() public AbpApiProxyScriptingOptions()
{ {
Generators = new Dictionary<string, Type>(); Generators = new Dictionary<string, Type>();
PropertyNameGenerator = propertyInfo =>
{
var jsonPropertyNameAttribute = propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>(true);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = propertyInfo.GetSingleAttributeOrNull<Newtonsoft.Json.JsonPropertyAttribute>(true);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
return null;
};
} }
} }
} }

3
framework/src/Volo.Abp.Sms.Aliyun/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
framework/src/Volo.Abp.Sms.Aliyun/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>

24
framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props"/>
<Import Project="..\..\..\common.props"/>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Sms.Aliyun</AssemblyName>
<PackageId>Volo.Abp.Sms.Aliyun</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace/>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Sms\Volo.Abp.Sms.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="1.0.2"/>
</ItemGroup>
</Project>

11
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Sms.Aliyun
{
public class AbpAliyunSmsOptions
{
public string AccessKeySecret { get; set; }
public string AccessKeyId { get; set; }
public string EndPoint { get; set; }
}
}

16
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs

@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsModule))]
public class AbpSmsAliyunModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(configuration.GetSection("AbpAliyunSms"));
}
}
}

43
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using AliyunClient = AlibabaCloud.SDK.Dysmsapi20170525.Client;
using AliyunConfig = AlibabaCloud.OpenApiClient.Models.Config;
using AliyunSendSmsRequest = AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender : ISmsSender, ITransientDependency
{
protected AbpAliyunSmsOptions Options { get; }
public AliyunSmsSender(IOptionsSnapshot<AbpAliyunSmsOptions> options)
{
Options = options.Value;
}
public async Task SendAsync(SmsMessage smsMessage)
{
var client = CreateClient();
await client.SendSmsAsync(new AliyunSendSmsRequest
{
PhoneNumbers = smsMessage.PhoneNumber,
SignName = smsMessage.Properties.GetOrDefault("SignName") as string,
TemplateCode = smsMessage.Properties.GetOrDefault("TemplateCode") as string,
TemplateParam = smsMessage.Text
});
}
protected virtual AliyunClient CreateClient()
{
return new(new AliyunConfig
{
AccessKeyId = Options.AccessKeyId,
AccessKeySecret = Options.AccessKeySecret,
Endpoint = Options.EndPoint
});
}
}
}

26
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<UserSecretsId>9f0d2c00-80c1-435b-bfab-2c39c8249091</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
</ItemGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

12
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs

@ -0,0 +1,12 @@
using Volo.Abp.Testing;
namespace Volo.Abp.Sms.Aliyun
{
public class AbpSmsAliyunTestBase : AbpIntegratedTest<AbpSmsAliyunTestsModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

18
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs

@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsAliyunModule))]
public class AbpSmsAliyunTestsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(
configuration.GetSection("AbpAliyunSms")
);
}
}
}

37
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Xunit;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender_Tests : AbpSmsAliyunTestBase
{
private readonly ISmsSender _smsSender;
private readonly IConfiguration _configuration;
public AliyunSmsSender_Tests()
{
_configuration = GetRequiredService<IConfiguration>();
_smsSender = GetRequiredService<ISmsSender>();
}
[Fact]
public async Task SendSms_Test()
{
var config = _configuration.GetSection("AbpAliyunSms");
// Please fill in the real parameters in the appsettings.json file.
if (config["AccessKeyId"] == "<Enter your AccessKeyId from Aliyun>")
{
return;
}
var msg = new SmsMessage(config["TargetPhoneNumber"],
config["TemplateParam"]);
msg.Properties.Add("SignName", config["SignName"]);
msg.Properties.Add("TemplateCode", config["TemplateCode"]);
await _smsSender.SendAsync(msg);
}
}
}

11
framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json

@ -0,0 +1,11 @@
{
"AbpAliyunSms": {
"AccessKeySecret": "<Enter your AccessKeySecret from Aliyun>",
"AccessKeyId": "<Enter your AccessKeyId from Aliyun>",
"EndPoint": "<Enter your EndPoint from Aliyun>",
"TargetPhoneNumber": "<Enter the target phone number to receive the SMS>",
"SignName": "<Enter the SignName from Aliyun>",
"TemplateCode": "<Enter the TemplateCode you need to send>",
"TemplateParam": "<Enter the template parameters>"
}
}

7
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs

@ -1,20 +1,13 @@
using System; using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs namespace Volo.CmsKit.Admin.Blogs
{ {
[Serializable] [Serializable]
public class BlogDto : EntityDto<Guid> public class BlogDto : EntityDto<Guid>
{ {
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; } public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; } public string Slug { get; set; }
} }
} }

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
public class CreateBlogDto
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; }
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs

@ -3,7 +3,7 @@ using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Admin.Blogs namespace Volo.CmsKit.Admin.Blogs
{ {
public interface IBlogAdminAppService : ICrudAppService<BlogDto, Guid, BlogGetListInput> public interface IBlogAdminAppService : ICrudAppService<BlogDto, Guid, BlogGetListInput, CreateBlogDto, UpdateBlogDto>
{ {
} }
} }

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
public class UpdateBlogDto
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; }
}
}

69
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs

@ -1,10 +1,8 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.GlobalFeatures; using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Blogs; using Volo.CmsKit.Blogs;
using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.GlobalFeatures;
@ -14,24 +12,63 @@ namespace Volo.CmsKit.Admin.Blogs
{ {
[RequiresGlobalFeature(typeof(BlogsFeature))] [RequiresGlobalFeature(typeof(BlogsFeature))]
[Authorize(CmsKitAdminPermissions.Blogs.Default)] [Authorize(CmsKitAdminPermissions.Blogs.Default)]
public class BlogAdminAppService : CrudAppService<Blog, BlogDto, Guid, BlogGetListInput>, IBlogAdminAppService public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppService
{ {
public BlogAdminAppService(IRepository<Blog, Guid> repository) : base(repository) protected IBlogRepository BlogRepository { get; }
protected BlogManager BlogManager { get; }
public BlogAdminAppService(IBlogRepository blogRepository, BlogManager blogManager)
{ {
GetListPolicyName = CmsKitAdminPermissions.Blogs.Default; BlogRepository = blogRepository;
GetPolicyName = CmsKitAdminPermissions.Blogs.Default; BlogManager = blogManager;
CreatePolicyName = CmsKitAdminPermissions.Blogs.Create; }
UpdatePolicyName = CmsKitAdminPermissions.Blogs.Update;
DeletePolicyName = CmsKitAdminPermissions.Blogs.Delete; public virtual async Task<BlogDto> GetAsync(Guid id)
{
var blog = await BlogRepository.GetAsync(id);
return ObjectMapper.Map<Blog, BlogDto>(blog);
}
public virtual async Task<PagedResultDto<BlogDto>> GetListAsync(BlogGetListInput input)
{
var totalCount = await BlogRepository.GetCountAsync(input.Filter);
var blogs = await BlogRepository.GetListAsync(
input.Filter,
input.Sorting,
input.MaxResultCount,
input.SkipCount);
return new PagedResultDto<BlogDto>(totalCount, ObjectMapper.Map<List<Blog>, List<BlogDto>>(blogs));
}
[Authorize(CmsKitAdminPermissions.Blogs.Create)]
public virtual async Task<BlogDto> CreateAsync(CreateBlogDto input)
{
var blog = await BlogManager.CreateAsync(input.Name, input.Slug);
await BlogRepository.InsertAsync(blog);
return ObjectMapper.Map<Blog, BlogDto>(blog);
}
[Authorize(CmsKitAdminPermissions.Blogs.Update)]
public virtual async Task<BlogDto> UpdateAsync(Guid id, UpdateBlogDto input)
{
var blog = await BlogRepository.GetAsync(id);
blog = await BlogManager.UpdateAsync(blog, input.Name, input.Slug);
await BlogRepository.UpdateAsync(blog);
return ObjectMapper.Map<Blog, BlogDto>(blog);
} }
protected override async Task<IQueryable<Blog>> CreateFilteredQueryAsync(BlogGetListInput input) [Authorize(CmsKitAdminPermissions.Blogs.Delete)]
public virtual Task DeleteAsync(Guid id)
{ {
var queryable = await base.CreateFilteredQueryAsync(input); return BlogRepository.DeleteAsync(id);
return queryable
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
x => x.Name.ToLower().Contains(input.Filter));
} }
} }
} }

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs

@ -37,8 +37,7 @@ namespace Volo.CmsKit.Admin
CreateMap<CreateBlogPostDto, BlogPost>(MemberList.Source); CreateMap<CreateBlogPostDto, BlogPost>(MemberList.Source);
CreateMap<UpdateBlogPostDto, BlogPost>(MemberList.Source); CreateMap<UpdateBlogPostDto, BlogPost>(MemberList.Source);
CreateMap<Blog, BlogDto>(MemberList.Destination) CreateMap<Blog, BlogDto>();
.ReverseMap();
CreateMap<TagEntityTypeDefiniton, TagDefinitionDto>(MemberList.Destination); CreateMap<TagEntityTypeDefiniton, TagDefinitionDto>(MemberList.Destination);

33
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs

@ -8,15 +8,15 @@ namespace Volo.CmsKit.Admin.Tags
public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService
{ {
protected ITagDefinitionStore TagDefinitionStore { get; } protected ITagDefinitionStore TagDefinitionStore { get; }
protected IEntityTagManager EntityTagManager { get; } protected EntityTagManager EntityTagManager { get; }
protected ITagManager TagManager { get; } protected TagManager TagManager { get; }
protected ITagRepository TagRepository { get; } protected ITagRepository TagRepository { get; }
protected IEntityTagRepository EntityTagRepository { get; } protected IEntityTagRepository EntityTagRepository { get; }
public EntityTagAdminAppService( public EntityTagAdminAppService(
ITagDefinitionStore tagDefinitionStore, ITagDefinitionStore tagDefinitionStore,
IEntityTagManager entityTagManager, EntityTagManager entityTagManager,
ITagManager tagManager, TagManager tagManager,
ITagRepository tagRepository, ITagRepository tagRepository,
IEntityTagRepository entityTagRepository) IEntityTagRepository entityTagRepository)
{ {
@ -29,11 +29,11 @@ namespace Volo.CmsKit.Admin.Tags
public virtual async Task AddTagToEntityAsync(EntityTagCreateDto input) public virtual async Task AddTagToEntityAsync(EntityTagCreateDto input)
{ {
var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType); var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionAsync(input.EntityType);
await CheckPolicyAsync(definition.CreatePolicy); await CheckPolicyAsync(definition.CreatePolicy);
var tag = await TagManager.GetOrAddAsync(input.EntityType, input.TagName, CurrentTenant?.Id); var tag = await TagManager.GetOrAddAsync(input.EntityType, input.TagName);
await EntityTagManager.AddTagToEntityAsync( await EntityTagManager.AddTagToEntityAsync(
tag.Id, tag.Id,
@ -44,7 +44,7 @@ namespace Volo.CmsKit.Admin.Tags
public virtual async Task RemoveTagFromEntityAsync(EntityTagRemoveDto input) public virtual async Task RemoveTagFromEntityAsync(EntityTagRemoveDto input)
{ {
var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType); var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionAsync(input.EntityType);
await CheckPolicyAsync(definition.DeletePolicy); await CheckPolicyAsync(definition.DeletePolicy);
@ -57,24 +57,11 @@ namespace Volo.CmsKit.Admin.Tags
public virtual async Task SetEntityTagsAsync(EntityTagSetDto input) public virtual async Task SetEntityTagsAsync(EntityTagSetDto input)
{ {
var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType); var definition = await TagDefinitionStore.GetTagEntityTypeDefinitionAsync(input.EntityType);
await CheckPolicyAsync(definition.UpdatePolicy); await CheckPolicyAsync(definition.UpdatePolicy);
var existingTags = await EntityTagManager.SetEntityTagsAsync(input.EntityType, input.EntityId, input.Tags);
await TagRepository.GetAllRelatedTagsAsync(input.EntityType, input.EntityId, CurrentTenant?.Id);
var deletedTags = existingTags.Where(x => !input.Tags.Contains(x.Name)).ToList();
var addedTags = input.Tags.Where(x => !existingTags.Any(a => a.Name == x));
await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray());
foreach (var addedTag in addedTags)
{
var tag = await TagManager.GetOrAddAsync(input.EntityType, addedTag, CurrentTenant?.Id);
await EntityTagManager.AddTagToEntityAsync(tag.Id, input.EntityType, input.EntityId, CurrentTenant?.Id);
}
} }
} }
} }

28
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs

@ -22,17 +22,19 @@ namespace Volo.CmsKit.Admin.Tags
TagUpdateDto>, TagUpdateDto>,
ITagAdminAppService ITagAdminAppService
{ {
protected ITagManager TagManager { get; } protected TagManager TagManager { get; }
protected ITagDefinitionStore TagDefinitionStore { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; } protected IStringLocalizerFactory StringLocalizerFactory { get; }
public TagAdminAppService( public TagAdminAppService(
IRepository<Tag, Guid> repository, IRepository<Tag, Guid> repository,
ITagManager tagManager, TagManager tagManager,
ITagDefinitionStore tagDefinitionStore,
IStringLocalizerFactory stringLocalizerFactory) : base(repository) IStringLocalizerFactory stringLocalizerFactory) : base(repository)
{ {
TagManager = tagManager; TagManager = tagManager;
StringLocalizerFactory = stringLocalizerFactory; TagDefinitionStore = tagDefinitionStore;
StringLocalizerFactory = stringLocalizerFactory;
GetListPolicyName = CmsKitAdminPermissions.Tags.Default; GetListPolicyName = CmsKitAdminPermissions.Tags.Default;
GetPolicyName = CmsKitAdminPermissions.Tags.Default; GetPolicyName = CmsKitAdminPermissions.Tags.Default;
@ -44,12 +46,13 @@ namespace Volo.CmsKit.Admin.Tags
[Authorize(CmsKitAdminPermissions.Tags.Create)] [Authorize(CmsKitAdminPermissions.Tags.Create)]
public override async Task<TagDto> CreateAsync(TagCreateDto input) public override async Task<TagDto> CreateAsync(TagCreateDto input)
{ {
var tag = await TagManager.InsertAsync( var tag = await TagManager.CreateAsync(
GuidGenerator.Create(), GuidGenerator.Create(),
input.EntityType, input.EntityType,
input.Name, input.Name);
CurrentTenant?.Id);
await Repository.InsertAsync(tag);
return await MapToGetOutputDtoAsync(tag); return await MapToGetOutputDtoAsync(tag);
} }
@ -60,11 +63,14 @@ namespace Volo.CmsKit.Admin.Tags
id, id,
input.Name); input.Name);
await Repository.UpdateAsync(tag);
return await MapToGetOutputDtoAsync(tag); return await MapToGetOutputDtoAsync(tag);
} }
protected override IQueryable<Tag> CreateFilteredQuery(TagGetListInput input)
protected override async Task<IQueryable<Tag>> CreateFilteredQueryAsync(TagGetListInput input)
{ {
return base.CreateFilteredQuery(input) return (await base.CreateFilteredQueryAsync(input))
.WhereIf( .WhereIf(
!input.Filter.IsNullOrEmpty(), !input.Filter.IsNullOrEmpty(),
x => x =>
@ -74,7 +80,7 @@ namespace Volo.CmsKit.Admin.Tags
public virtual async Task<List<TagDefinitionDto>> GetTagDefinitionsAsync() public virtual async Task<List<TagDefinitionDto>> GetTagDefinitionsAsync()
{ {
var definitions = await TagManager.GetTagDefinitionsAsync(); var definitions = await TagDefinitionStore.GetTagEntityTypeDefinitionListAsync();
return definitions return definitions
.Select(s => .Select(s =>

39
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs

@ -1,9 +1,6 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
@ -27,42 +24,40 @@ namespace Volo.CmsKit.Admin.Blogs
BlogAdminAppService = blogAdminAppService; BlogAdminAppService = blogAdminAppService;
} }
[HttpPost]
[Authorize(CmsKitAdminPermissions.Blogs.Create)]
public Task<BlogDto> CreateAsync(BlogDto input)
{
return BlogAdminAppService.CreateAsync(input);
}
[HttpDelete]
[Route("{id}")]
[Authorize(CmsKitAdminPermissions.Blogs.Delete)]
public Task DeleteAsync(Guid id)
{
return BlogAdminAppService.DeleteAsync(id);
}
[HttpGet] [HttpGet]
[Route("{id}")] [Route("{id}")]
[Authorize(CmsKitAdminPermissions.Blogs.Default)]
public Task<BlogDto> GetAsync(Guid id) public Task<BlogDto> GetAsync(Guid id)
{ {
return BlogAdminAppService.GetAsync(id); return BlogAdminAppService.GetAsync(id);
} }
[HttpGet] [HttpGet]
[Authorize(CmsKitAdminPermissions.Blogs.Default)] public Task<PagedResultDto<BlogDto>> GetListAsync(BlogGetListInput input)
public Task<PagedResultDto<BlogDto>> GetListAsync([FromQuery] BlogGetListInput input)
{ {
return BlogAdminAppService.GetListAsync(input); return BlogAdminAppService.GetListAsync(input);
} }
[HttpPost]
[Authorize(CmsKitAdminPermissions.Blogs.Create)]
public Task<BlogDto> CreateAsync(CreateBlogDto input)
{
return BlogAdminAppService.CreateAsync(input);
}
[HttpPut] [HttpPut]
[Route("{id}")] [Route("{id}")]
[Authorize(CmsKitAdminPermissions.Blogs.Update)] [Authorize(CmsKitAdminPermissions.Blogs.Update)]
public Task<BlogDto> UpdateAsync(Guid id, BlogDto input) public Task<BlogDto> UpdateAsync(Guid id, UpdateBlogDto input)
{ {
return BlogAdminAppService.UpdateAsync(id, input); return BlogAdminAppService.UpdateAsync(id, input);
} }
[HttpDelete]
[Route("{id}")]
[Authorize(CmsKitAdminPermissions.Blogs.Delete)]
public Task DeleteAsync(Guid id)
{
return BlogAdminAppService.DeleteAsync(id);
}
} }
} }

3
modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Tags/TagAppService.cs

@ -20,8 +20,7 @@ namespace Volo.CmsKit.Tags
{ {
var entities = await TagRepository.GetAllRelatedTagsAsync( var entities = await TagRepository.GetAllRelatedTagsAsync(
entityType, entityType,
entityId, entityId);
CurrentTenant.Id);
return ObjectMapper.Map<List<Tag>, List<TagDto>>(entities); return ObjectMapper.Map<List<Tag>, List<TagDto>>(entities);
} }

5
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs

@ -16,6 +16,11 @@
} }
public static class Blogs public static class Blogs
{
public const string SlugAlreadyExists = "CmsKit:Blog:0001";
}
public static class BlogPosts
{ {
public const string SlugAlreadyExist = "CmsKit:BlogPost:0001"; public const string SlugAlreadyExist = "CmsKit:BlogPost:0001";
} }

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -3,6 +3,7 @@
"texts": { "texts": {
"CmsKit:0002": "Content already exists!", "CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.", "CmsKit:0003": "The entity {0} is not taggable.",
"CmsKit:Blog:0001": "The given slug ({Slug}) already exists!",
"CmsKit:BlogPost:0001": "The given slug already exists!", "CmsKit:BlogPost:0001": "The given slug already exists!",
"CmsKit:Media:0001": "'{Name}' is not a valid media name.", "CmsKit:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Page:0001": "The given url ({0}) already exists.", "CmsKit:Page:0001": "The given url ({0}) already exists.",

24
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs

@ -9,17 +9,6 @@ namespace Volo.CmsKit.Blogs
{ {
public class Blog : FullAuditedAggregateRoot<Guid>, IMultiTenant public class Blog : FullAuditedAggregateRoot<Guid>, IMultiTenant
{ {
public Blog(
Guid id,
[NotNull] string name,
[NotNull] string slug,
[CanBeNull] Guid? tenantId = null) : base(id)
{
SetName(name);
SetSlug(slug);
TenantId = tenantId;
}
[NotNull] [NotNull]
public virtual string Name { get; protected set; } public virtual string Name { get; protected set; }
@ -27,15 +16,22 @@ namespace Volo.CmsKit.Blogs
public virtual string Slug { get; protected set; } public virtual string Slug { get; protected set; }
public virtual Guid? TenantId { get; protected set; } public virtual Guid? TenantId { get; protected set; }
protected internal Blog(Guid id, [NotNull] string name, [NotNull] string slug, [CanBeNull] Guid? tenantId = null) : base(id)
{
SetName(name);
SetSlug(slug);
TenantId = tenantId;
}
public virtual void SetName(string name) public virtual void SetName(string name)
{ {
Name = Check.NotNullOrWhiteSpace(name, nameof(name), maxLength: BlogConsts.MaxNameLength); Name = Check.NotNullOrWhiteSpace(name, nameof(name), BlogConsts.MaxNameLength);
} }
public virtual void SetSlug(string slug) public virtual void SetSlug(string slug)
{ {
Check.NotNullOrWhiteSpace(slug, nameof(slug), maxLength: BlogConsts.MaxNameLength); Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogConsts.MaxNameLength);
Slug = slug.NormalizeSlug(); Slug = slug.NormalizeSlug();
} }

44
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogManager.cs

@ -0,0 +1,44 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Services;
namespace Volo.CmsKit.Blogs
{
public class BlogManager : DomainService
{
protected IBlogRepository BlogRepository { get; }
public BlogManager(IBlogRepository blogRepository)
{
BlogRepository = blogRepository;
}
public virtual async Task<Blog> CreateAsync([NotNull] string name, [NotNull] string slug)
{
await CheckSlugAsync(slug);
return new Blog(GuidGenerator.Create(), name, slug, CurrentTenant.Id);
}
public virtual async Task<Blog> UpdateAsync([NotNull] Blog blog, [NotNull] string name, [NotNull] string slug)
{
if (slug != blog.Slug)
{
await CheckSlugAsync(slug);
}
blog.SetName(name);
blog.SetSlug(slug);
return blog;
}
protected virtual async Task CheckSlugAsync([NotNull] string slug)
{
if (await BlogRepository.SlugExistsAsync(slug))
{
throw new BlogSlugAlreadyExistException(slug);
}
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs

@ -19,7 +19,7 @@ namespace Volo.CmsKit.Blogs
Slug = slug; Slug = slug;
BlogId = blogId; BlogId = blogId;
Code = CmsKitErrorCodes.Blogs.SlugAlreadyExist; Code = CmsKitErrorCodes.BlogPosts.SlugAlreadyExist;
WithData(nameof(Slug), Slug); WithData(nameof(Slug), Slug);
WithData(nameof(BlogId), BlogId); WithData(nameof(BlogId), BlogId);

22
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogSlugAlreadyExistException.cs

@ -0,0 +1,22 @@
using System;
using System.Runtime.Serialization;
using Volo.Abp;
namespace Volo.CmsKit.Blogs
{
[Serializable]
public class BlogSlugAlreadyExistException : BusinessException
{
public BlogSlugAlreadyExistException(string slug)
{
Code = CmsKitErrorCodes.Blogs.SlugAlreadyExists;
WithData(nameof(Blog.Slug), slug);
}
public BlogSlugAlreadyExistException(
SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context)
{
}
}
}

21
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
@ -7,7 +8,23 @@ namespace Volo.CmsKit.Blogs
{ {
public interface IBlogRepository : IBasicRepository<Blog, Guid> public interface IBlogRepository : IBasicRepository<Blog, Guid>
{ {
public Task<Blog> GetBySlugAsync(string slug, CancellationToken cancellationToken = default); Task<List<Blog>> GetListAsync(
Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default); string filter = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default
);
Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default
);
Task<Blog> GetBySlugAsync(string slug, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default);
Task<bool> SlugExistsAsync(string slug, CancellationToken cancellationToken = default);
} }
} }

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs

@ -33,7 +33,7 @@ namespace Volo.CmsKit.MediaDescriptors
public void SetName(string name) public void SetName(string name)
{ {
if (!name.IsValidMediaFileName()) if (!MediaDescriptorCheck.IsValidMediaFileName(name))
{ {
throw new InvalidMediaDescriptorNameException(name); throw new InvalidMediaDescriptorNameException(name);
} }

4
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/Extensions/MediaDescriptorExtensions.cs → modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptorCheck.cs

@ -3,9 +3,9 @@ using System.Linq;
namespace Volo.CmsKit.MediaDescriptors.Extensions namespace Volo.CmsKit.MediaDescriptors.Extensions
{ {
public static class MediaDescriptorExtensions public static class MediaDescriptorCheck
{ {
public static bool IsValidMediaFileName(this string name) public static bool IsValidMediaFileName(string name)
{ {
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs

@ -5,6 +5,6 @@ namespace Volo.CmsKit.Tags
public class CmsKitTagOptions public class CmsKitTagOptions
{ {
[NotNull] [NotNull]
public TagEntityTypeDefinitionDictionary EntityTypes { get; } = new TagEntityTypeDefinitionDictionary(); public TagEntityTypeDefinitions EntityTypes { get; } = new TagEntityTypeDefinitions();
} }
} }

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs

@ -24,7 +24,7 @@ namespace Volo.CmsKit.Tags
/// <param name="entityType">EntityType to get definition.</param> /// <param name="entityType">EntityType to get definition.</param>
/// <exception cref="EntityNotTaggableException">Thrown when EntityType is not configured as taggable.</exception> /// <exception cref="EntityNotTaggableException">Thrown when EntityType is not configured as taggable.</exception>
/// <exception cref="InvalidOperationException">More than one element satisfies the condition in predicate.</exception> /// <exception cref="InvalidOperationException">More than one element satisfies the condition in predicate.</exception>
public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType) public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionAsync([NotNull] string entityType)
{ {
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); Check.NotNullOrWhiteSpace(entityType, nameof(entityType));

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs

@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging; using System;
using System; using System.Runtime.Serialization;
using Volo.Abp; using Volo.Abp;
namespace Volo.CmsKit.Tags namespace Volo.CmsKit.Tags
@ -7,13 +7,7 @@ namespace Volo.CmsKit.Tags
[Serializable] [Serializable]
public class EntityNotTaggableException : BusinessException public class EntityNotTaggableException : BusinessException
{ {
public EntityNotTaggableException( public EntityNotTaggableException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context)
string code = null,
string message = null,
string details = null,
Exception innerException = null,
LogLevel logLevel = LogLevel.Warning)
: base(code, message, details, innerException, logLevel)
{ {
} }

30
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs

@ -1,22 +1,30 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
namespace Volo.CmsKit.Tags namespace Volo.CmsKit.Tags
{ {
public class EntityTagManager : DomainService, IEntityTagManager public class EntityTagManager : DomainService
{ {
protected IEntityTagRepository EntityTagRepository { get; } protected IEntityTagRepository EntityTagRepository { get; }
protected ITagRepository TagRepository { get; }
protected ITagDefinitionStore TagDefinitionStore { get; } protected ITagDefinitionStore TagDefinitionStore { get; }
protected TagManager TagManager { get; }
public EntityTagManager( public EntityTagManager(
IEntityTagRepository entityTagRepository, IEntityTagRepository entityTagRepository,
ITagDefinitionStore tagDefinitionStore) ITagRepository tagRepository,
ITagDefinitionStore tagDefinitionStore,
TagManager tagManager)
{ {
EntityTagRepository = entityTagRepository; EntityTagRepository = entityTagRepository;
TagRepository = tagRepository;
TagDefinitionStore = tagDefinitionStore; TagDefinitionStore = tagDefinitionStore;
TagManager = tagManager;
} }
public virtual async Task<EntityTag> AddTagToEntityAsync( public virtual async Task<EntityTag> AddTagToEntityAsync(
@ -45,5 +53,23 @@ namespace Volo.CmsKit.Tags
var entityTag = await EntityTagRepository.FindAsync(tagId, entityId, tenantId, cancellationToken); var entityTag = await EntityTagRepository.FindAsync(tagId, entityId, tenantId, cancellationToken);
await EntityTagRepository.DeleteAsync(entityTag, cancellationToken: cancellationToken); await EntityTagRepository.DeleteAsync(entityTag, cancellationToken: cancellationToken);
} }
public async Task SetEntityTagsAsync(string entityType, string entityId, List<string> tags)
{
var existingTags =
await TagRepository.GetAllRelatedTagsAsync(entityType, entityId);
var deletedTags = existingTags.Where(x => !tags.Contains(x.Name)).ToList();
var addedTags = tags.Where(x => !existingTags.Any(a => a.Name == x));
await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray());
foreach (var addedTag in addedTags)
{
var tag = await TagManager.GetOrAddAsync(entityType, addedTag);
await AddTagToEntityAsync(tag.Id, entityType, entityId, CurrentTenant?.Id);
}
}
} }
} }

24
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs

@ -1,24 +0,0 @@
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Volo.CmsKit.Tags
{
public interface IEntityTagManager
{
Task<EntityTag> AddTagToEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task RemoveTagFromEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs

@ -8,7 +8,7 @@ namespace Volo.CmsKit.Tags
{ {
Task<List<TagEntityTypeDefiniton>> GetTagEntityTypeDefinitionListAsync(); Task<List<TagEntityTypeDefiniton>> GetTagEntityTypeDefinitionListAsync();
Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType); Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionAsync([NotNull] string entityType);
Task<bool> IsDefinedAsync([NotNull] string entityType); Task<bool> IsDefinedAsync([NotNull] string entityType);
} }

33
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs

@ -1,33 +0,0 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Tags
{
public interface ITagManager : IDomainService
{
Task<Tag> InsertAsync(
Guid id,
[NotNull] string entityType,
[NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<Tag> UpdateAsync(
Guid id,
[NotNull] string name,
CancellationToken cancellationToken = default);
Task<Tag> GetOrAddAsync(
[NotNull] string entityType,
[NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync(CancellationToken cancellationToken = default);
}
}

4
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagRepository.cs

@ -12,25 +12,21 @@ namespace Volo.CmsKit.Tags
Task<Tag> GetAsync( Task<Tag> GetAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<bool> AnyAsync( Task<bool> AnyAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<Tag> FindAsync( Task<Tag> FindAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<List<Tag>> GetAllRelatedTagsAsync( Task<List<Tag>> GetAllRelatedTagsAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string entityId, [NotNull] string entityId,
Guid? tenantId = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
} }
} }

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs

@ -1,11 +0,0 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefinitionDictionary : List<TagEntityTypeDefiniton>
{
}
}

8
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitions.cs

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefinitions : List<TagEntityTypeDefiniton>
{
}
}

51
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs

@ -3,11 +3,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
namespace Volo.CmsKit.Tags namespace Volo.CmsKit.Tags
{ {
public class TagManager : DomainService, ITagManager public class TagManager : DomainService
{ {
protected ITagRepository TagRepository { get; } protected ITagRepository TagRepository { get; }
protected ITagDefinitionStore TagDefinitionStore { get; } protected ITagDefinitionStore TagDefinitionStore { get; }
@ -18,56 +19,52 @@ namespace Volo.CmsKit.Tags
TagDefinitionStore = tagDefinitionStore; TagDefinitionStore = tagDefinitionStore;
} }
public virtual async Task<Tag> GetOrAddAsync([NotNull] string entityType, [NotNull] string name, public virtual async Task<Tag> GetOrAddAsync([NotNull] string entityType, [NotNull] string name)
Guid? tenantId = null, CancellationToken cancellationToken = default)
{ {
var entity = await TagRepository.FindAsync(entityType, name, tenantId, cancellationToken); var tag = await TagRepository.FindAsync(entityType, name);
if (entity == null) if (tag == null)
{ {
entity = await InsertAsync(GuidGenerator.Create(), entityType, name, tenantId, cancellationToken); tag = await CreateAsync(GuidGenerator.Create(), entityType, name);
await TagRepository.InsertAsync(tag);
} }
return entity; return tag;
} }
public virtual async Task<Tag> InsertAsync(Guid id, [NotNull] string entityType, [NotNull] string name, public virtual async Task<Tag> CreateAsync(Guid id,
Guid? tenantId = null, CancellationToken cancellationToken = default) [NotNull] string entityType,
[NotNull] string name)
{ {
if (!await TagDefinitionStore.IsDefinedAsync(entityType)) if (!await TagDefinitionStore.IsDefinedAsync(entityType))
{ {
throw new EntityNotTaggableException(entityType); throw new EntityNotTaggableException(entityType);
} }
if (await TagRepository.AnyAsync(entityType, name, tenantId, cancellationToken)) if (await TagRepository.AnyAsync(entityType, name))
{ {
throw new TagAlreadyExistException(entityType, name); throw new TagAlreadyExistException(entityType, name);
} }
return await TagRepository.InsertAsync(new Tag(id, entityType, name, tenantId), return
cancellationToken: cancellationToken); new Tag(id, entityType, name, CurrentTenant.Id);
} }
public virtual async Task<Tag> UpdateAsync(Guid id, [NotNull] string name, public virtual async Task<Tag> UpdateAsync(Guid id, [NotNull] string name)
CancellationToken cancellationToken = default)
{ {
var entity = await TagRepository.GetAsync(id, cancellationToken: cancellationToken); Check.NotNullOrEmpty(name, nameof(name));
if (name != entity.Name && var tag = await TagRepository.GetAsync(id);
await TagRepository.AnyAsync(entity.EntityType, name, entity.TenantId, cancellationToken))
if (name != tag.Name &&
await TagRepository.AnyAsync(tag.EntityType, name))
{ {
throw new TagAlreadyExistException(entity.EntityType, name); throw new TagAlreadyExistException(tag.EntityType, name);
} }
entity.SetName(name); tag.SetName(name);
return await TagRepository.UpdateAsync(entity, cancellationToken: cancellationToken);
}
public virtual Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync( return tag;
CancellationToken cancellationToken = default)
{
return TagDefinitionStore.GetTagEntityTypeDefinitionListAsync();
} }
} }
} }

46
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs

@ -1,9 +1,11 @@
using Microsoft.EntityFrameworkCore; using System;
using System; using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates; using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
@ -17,15 +19,47 @@ namespace Volo.CmsKit.Blogs
{ {
} }
public virtual async Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default) public virtual async Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default)
{ {
return await (await GetQueryableAsync()).AnyAsync(x => x.Id == blogId, GetCancellationToken(cancellationToken)); return await (await GetQueryableAsync()).AnyAsync(x => x.Id == id, GetCancellationToken(cancellationToken));
} }
public virtual Task<Blog> GetBySlugAsync([NotNull]string slug, CancellationToken cancellationToken = default) public virtual async Task<bool> SlugExistsAsync(string slug, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).AnyAsync(x => x.Slug == slug, GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Blog>> GetListAsync(
string filter = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default)
{
var query = await GetListQueryAsync(filter);
return await query.OrderBy(sorting ?? "creationTime desc")
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
var query = await GetListQueryAsync(filter);
return await query.LongCountAsync(GetCancellationToken(cancellationToken));
}
public virtual Task<Blog> GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(slug, nameof(slug)); Check.NotNullOrEmpty(slug, nameof(slug));
return GetAsync(x => x.Slug == slug, cancellationToken: GetCancellationToken(cancellationToken)); return GetAsync(x => x.Slug == slug, cancellationToken: GetCancellationToken(cancellationToken));
} }
protected virtual async Task<IQueryable<Blog>> GetListQueryAsync(string filter = null)
{
return (await GetDbSetAsync())
.WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter));
}
} }
} }

16
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreTagRepository.cs

@ -21,7 +21,6 @@ namespace Volo.CmsKit.Tags
public virtual async Task<bool> AnyAsync( public virtual async Task<bool> AnyAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
@ -29,15 +28,13 @@ namespace Volo.CmsKit.Tags
return await (await GetDbSetAsync()).AnyAsync(x => return await (await GetDbSetAsync()).AnyAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
GetCancellationToken(cancellationToken)); GetCancellationToken(cancellationToken));
} }
public virtual Task<Tag> GetAsync( public virtual Task<Tag> GetAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
@ -45,15 +42,13 @@ namespace Volo.CmsKit.Tags
return GetAsync(x => return GetAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
cancellationToken: GetCancellationToken(cancellationToken)); cancellationToken: GetCancellationToken(cancellationToken));
} }
public virtual Task<Tag> FindAsync( public virtual Task<Tag> FindAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
@ -61,28 +56,25 @@ namespace Volo.CmsKit.Tags
return FindAsync(x => return FindAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
cancellationToken: GetCancellationToken(cancellationToken)); cancellationToken: GetCancellationToken(cancellationToken));
} }
public virtual async Task<List<Tag>> GetAllRelatedTagsAsync( public virtual async Task<List<Tag>> GetAllRelatedTagsAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string entityId, [NotNull] string entityId,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
Check.NotNullOrEmpty(entityId, nameof(entityId)); Check.NotNullOrEmpty(entityId, nameof(entityId));
var entityTagIds = await (await GetDbContextAsync()).Set<EntityTag>() var entityTagIds = await (await GetDbContextAsync()).Set<EntityTag>()
.Where(q => q.EntityId == entityId && q.TenantId == tenantId) .Where(q => q.EntityId == entityId)
.Select(q => q.TagId) .Select(q => q.TagId)
.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));
var query = (await GetDbSetAsync()) var query = (await GetDbSetAsync())
.Where(x => x.EntityType == entityType && .Where(x => x.EntityType == entityType &&
x.TenantId == tenantId &&
entityTagIds.Contains(x.Id)); entityTagIds.Contains(x.Id));
return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));

56
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs

@ -1,8 +1,12 @@
using MongoDB.Driver.Core.Operations; using System;
using System; using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
@ -16,18 +20,54 @@ namespace Volo.CmsKit.MongoDB.Blogs
{ {
} }
public virtual async Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default) public virtual async Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default)
{ {
return await AsyncExecuter.AnyAsync( var token = GetCancellationToken(cancellationToken);
await GetQueryableAsync(), return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Id == id, token);
x => x.Id == blogId,
cancellationToken);
} }
public virtual Task<Blog> GetBySlugAsync([NotNull]string slug, CancellationToken cancellationToken = default) public virtual async Task<bool> SlugExistsAsync(string slug, CancellationToken cancellationToken = default)
{
var token = GetCancellationToken(cancellationToken);
return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token);
}
public virtual async Task<List<Blog>> GetListAsync(
string filter = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default)
{
var token = GetCancellationToken(cancellationToken);
var query = await GetListQueryAsync(filter, token);
return await query.OrderBy(sorting ?? "creationTime desc")
.As<IMongoQueryable<Blog>>()
.PageBy<Blog, IMongoQueryable<Blog>>(skipCount, maxResultCount)
.ToListAsync(token);
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
var token = GetCancellationToken(cancellationToken);
var query = await GetListQueryAsync(filter, token);
return await query.As<IMongoQueryable<Blog>>().LongCountAsync(token);
}
public virtual Task<Blog> GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(slug, nameof(slug)); Check.NotNullOrEmpty(slug, nameof(slug));
return GetAsync(x => x.Slug == slug, cancellationToken: cancellationToken); return GetAsync(x => x.Slug == slug, cancellationToken: cancellationToken);
} }
protected virtual async Task<IQueryable<Blog>> GetListQueryAsync(string filter = null, CancellationToken cancellationToken = default)
{
return (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)))
.WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter));
}
} }
} }

16
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoTagRepository.cs

@ -22,7 +22,6 @@ namespace Volo.CmsKit.MongoDB.Tags
public async Task<bool> AnyAsync( public async Task<bool> AnyAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
@ -31,28 +30,24 @@ namespace Volo.CmsKit.MongoDB.Tags
return await (await GetMongoQueryableAsync(cancellationToken)) return await (await GetMongoQueryableAsync(cancellationToken))
.AnyAsync(x => .AnyAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
GetCancellationToken(cancellationToken)); GetCancellationToken(cancellationToken));
} }
public Task<Tag> GetAsync( public Task<Tag> GetAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return GetAsync(x => return GetAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
cancellationToken: GetCancellationToken(cancellationToken)); cancellationToken: GetCancellationToken(cancellationToken));
} }
public Task<Tag> FindAsync( public Task<Tag> FindAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string name, [NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
@ -60,29 +55,26 @@ namespace Volo.CmsKit.MongoDB.Tags
return FindAsync(x => return FindAsync(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.Name == name && x.Name == name,
x.TenantId == tenantId,
cancellationToken: GetCancellationToken(cancellationToken)); cancellationToken: GetCancellationToken(cancellationToken));
} }
public virtual async Task<List<Tag>> GetAllRelatedTagsAsync( public virtual async Task<List<Tag>> GetAllRelatedTagsAsync(
[NotNull] string entityType, [NotNull] string entityType,
[NotNull] string entityId, [NotNull] string entityId,
Guid? tenantId = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Check.NotNullOrEmpty(entityType, nameof(entityType)); Check.NotNullOrEmpty(entityType, nameof(entityType));
Check.NotNullOrEmpty(entityId, nameof(entityId)); Check.NotNullOrEmpty(entityId, nameof(entityId));
var entityTagIds = await (await GetDbContextAsync(cancellationToken)).EntityTags.AsQueryable() var entityTagIds = await (await GetDbContextAsync(cancellationToken)).EntityTags.AsQueryable()
.Where(q => q.EntityId == entityId && q.TenantId == tenantId) .Where(q => q.EntityId == entityId)
.Select(q => q.TagId) .Select(q => q.TagId)
.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));
var query = (await GetMongoQueryableAsync(cancellationToken)) var query = (await GetMongoQueryableAsync(cancellationToken))
.Where(x => .Where(x =>
x.EntityType == entityType && x.EntityType == entityType &&
x.TenantId == tenantId &&
entityTagIds.Contains(x.Id)); entityTagIds.Contains(x.Id));
var result = await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); var result = await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));

92
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogAdminAppService_Tests.cs

@ -0,0 +1,92 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Domain.Entities;
using Volo.CmsKit.Admin.Blogs;
using Xunit;
namespace Volo.CmsKit.Blogs
{
public class BlogAdminAppService_Tests : CmsKitApplicationTestBase
{
protected IBlogAdminAppService BlogAdminAppService { get; }
protected CmsKitTestData CmsKitTestData { get; }
protected IBlogRepository BlogRepository { get; }
public BlogAdminAppService_Tests()
{
BlogAdminAppService = GetRequiredService<IBlogAdminAppService>();
CmsKitTestData = GetRequiredService<CmsKitTestData>();
BlogRepository = GetRequiredService<IBlogRepository>();
}
[Fact]
public async Task GetAsync()
{
var blog = await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id);
blog.Slug.ShouldBe(CmsKitTestData.BlogSlug);
}
[Fact]
public async Task GetListAsync()
{
var blogs = await BlogAdminAppService.GetListAsync(new BlogGetListInput());
blogs.TotalCount.ShouldBeGreaterThan(0);
blogs.Items.Any(x => x.Slug == CmsKitTestData.BlogSlug).ShouldBeTrue();
}
[Fact]
public async Task CreateAsync_ShouldWork()
{
var blog = await BlogAdminAppService.CreateAsync(new CreateBlogDto
{
Name = "News",
Slug = "latest-news"
});
blog.ShouldNotBeNull();
blog.Name.ShouldBe("News");
blog.Slug.ShouldBe("latest-news");
}
[Fact]
public async Task CreateAsync_ShouldThrow_WithExistSlug()
{
await Should.ThrowAsync<BlogSlugAlreadyExistException>(
async () =>
await BlogAdminAppService.CreateAsync(new CreateBlogDto
{
Name = "News",
Slug = CmsKitTestData.BlogSlug
}));
}
[Fact]
public async Task UpdateAsync_ShouldWork()
{
var blog = await BlogAdminAppService.UpdateAsync(CmsKitTestData.Blog_Id, new UpdateBlogDto
{
Name = "New Name",
Slug = "new-slug"
});
var updatedBlog = await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id);
updatedBlog.Name.ShouldBe("New Name");
updatedBlog.Slug.ShouldBe("new-slug");
}
[Fact]
public async Task DeleteAsync_ShouldWork()
{
await BlogAdminAppService.DeleteAsync(CmsKitTestData.Blog_Id);
await Should.ThrowAsync<EntityNotFoundException>(
async () =>
await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id)
);
}
}
}

10
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs

@ -48,5 +48,15 @@ namespace Volo.CmsKit.Tags
Name = _cmsKitTestData.Content_1_Tags[0], Name = _cmsKitTestData.Content_1_Tags[0],
})); }));
} }
public async Task GetTagDefinitionsAsync_ShouldWorkProperly_WithoutParameters()
{
var definitions = await _tagAdminAppService.GetTagDefinitionsAsync();
definitions.ShouldNotBeNull();
definitions.ShouldNotBeEmpty();
definitions.Count.ShouldBeGreaterThan(1);
definitions.ShouldContain(x => x.EntityType == _cmsKitTestData.TagDefinition_1_EntityType);
}
} }
} }

50
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/BlogManager_Test.cs

@ -0,0 +1,50 @@
using System;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.CmsKit.Blogs
{
public class BlogManager_Test : CmsKitDomainTestBase
{
protected IBlogRepository BlogRepository { get; }
protected BlogManager BlogManager { get; }
protected CmsKitTestData TestData { get; }
public BlogManager_Test()
{
BlogRepository = GetRequiredService<IBlogRepository>();
BlogManager = GetRequiredService<BlogManager>();
TestData = GetRequiredService<CmsKitTestData>();
}
[Fact]
public async Task BlogCreate_ShouldThrowException_WithExistSlug()
{
await Should.ThrowAsync<BlogSlugAlreadyExistException>(
async () =>
await BlogManager.CreateAsync("test-name", TestData.BlogSlug)
);
}
[Fact]
public async Task BlogCreate_ShouldWorkProperly()
{
var blog = await BlogManager.CreateAsync("test-name", "test-slug");
blog.ShouldNotBeNull();
blog.Id.ShouldNotBe(Guid.Empty);
}
[Fact]
public async Task BlogUpdate_ShouldWork()
{
var blog = await BlogRepository.GetAsync(TestData.Blog_Id);
await BlogManager.UpdateAsync(blog, "New name", "new-slug");
blog.Name.ShouldBe("New name");
blog.Slug.ShouldBe("new-slug");
}
}
}

54
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs

@ -1,4 +1,5 @@
using Shouldly; using Shouldly;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Guids; using Volo.Abp.Guids;
@ -9,14 +10,14 @@ namespace Volo.CmsKit.Tags
public class EntityTagManager_Tests : CmsKitDomainTestBase public class EntityTagManager_Tests : CmsKitDomainTestBase
{ {
private readonly CmsKitTestData _cmsKitTestData; private readonly CmsKitTestData _cmsKitTestData;
private readonly IEntityTagManager _entityTagManager; private readonly EntityTagManager _entityTagManager;
private readonly ITagRepository _tagRepository; private readonly ITagRepository _tagRepository;
private readonly IGuidGenerator _guidGenerator; private readonly IGuidGenerator _guidGenerator;
public EntityTagManager_Tests() public EntityTagManager_Tests()
{ {
_cmsKitTestData = GetRequiredService<CmsKitTestData>(); _cmsKitTestData = GetRequiredService<CmsKitTestData>();
_entityTagManager = GetRequiredService<IEntityTagManager>(); _entityTagManager = GetRequiredService<EntityTagManager>();
_tagRepository = GetRequiredService<ITagRepository>(); _tagRepository = GetRequiredService<ITagRepository>();
_guidGenerator = GetRequiredService<IGuidGenerator>(); _guidGenerator = GetRequiredService<IGuidGenerator>();
} }
@ -56,5 +57,54 @@ namespace Volo.CmsKit.Tags
tags.ShouldNotContain(x => x.Id == tagToDelete.Id); tags.ShouldNotContain(x => x.Id == tagToDelete.Id);
} }
[Fact]
public async Task SetEntityTagsAsync_ShouldWorkProperly_WithNonExistingTags()
{
var newTags = new List<string> { "non-existing-awesome-tag-a", "non-existing-awesome-tag-b" };
await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, newTags);
var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
tags.ShouldNotBeNull();
tags.ShouldNotBeEmpty();
tags.ForEach(tag => newTags.Contains(tag.Name));
}
[Fact]
public async Task SetEntityTagsAsync_ShouldWorkProperly_WithExistingTag()
{
var entityTags = new List<string>
{
_cmsKitTestData.TagName_1
};
await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, entityTags);
var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
tags.ShouldNotBeNull();
tags.ShouldNotBeEmpty();
tags.ForEach(tag => entityTags.Contains(tag.Name));
}
[Fact]
public async Task SetEntityTagsAsync_ShouldWorkProperly_WithExistingAndNonExistingTag()
{
var entityTags = new List<string>
{
"New Awesome Tag",
_cmsKitTestData.TagName_1
};
await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, entityTags);
var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
tags.ShouldNotBeNull();
tags.ShouldNotBeEmpty();
tags.ForEach(tag => entityTags.Contains(tag.Name));
}
} }
} }

28
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs

@ -53,24 +53,23 @@ namespace Volo.CmsKit.Tags
} }
[Fact] [Fact]
public async Task ShouldInsertAsync() public async Task ShouldCreateAsync()
{ {
var tagName = "Freshly Created New Tag"; var tagName = "Freshly Created New Tag";
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), _cmsKitTestData.EntityType1, tagName); var tag = await _tagManager.CreateAsync(Guid.NewGuid(), _cmsKitTestData.EntityType1, tagName);
tag.ShouldNotBeNull(); tag.ShouldNotBeNull();
var doesExist = await _tagRepository.AnyAsync(_cmsKitTestData.EntityType1, tagName); tag.Id.ShouldNotBe(Guid.Empty);
doesExist.ShouldBeTrue();
} }
[Fact] [Fact]
public async Task ShouldntInsertWithUnconfiguredEntityTypeAsync() public async Task ShouldntInsertWithUnconfiguredEntityTypeAsync()
{ {
var notConfiguredEntityType = "My.Namespace.SomeEntity"; var notConfiguredEntityType = "My.Namespace.SomeEntity";
var exception = await Should.ThrowAsync<EntityNotTaggableException>(async () => var exception = await Should.ThrowAsync<EntityNotTaggableException>(async () =>
await _tagManager.InsertAsync(Guid.NewGuid(), notConfiguredEntityType, "test")); await _tagManager.CreateAsync(Guid.NewGuid(), notConfiguredEntityType, "test"));
exception.ShouldNotBeNull(); exception.ShouldNotBeNull();
exception.Data[nameof(Tag.EntityType)].ShouldBe(notConfiguredEntityType); exception.Data[nameof(Tag.EntityType)].ShouldBe(notConfiguredEntityType);
@ -82,7 +81,7 @@ namespace Volo.CmsKit.Tags
var type = _cmsKitTestData.Content_1_EntityType; var type = _cmsKitTestData.Content_1_EntityType;
var name = _cmsKitTestData.Content_1_Tags[0]; var name = _cmsKitTestData.Content_1_Tags[0];
Should.Throw<Exception>(async () => await _tagManager.InsertAsync(Guid.NewGuid(), type, name)); Should.Throw<Exception>(async () => await _tagManager.CreateAsync(Guid.NewGuid(), type, name));
} }
[Fact] [Fact]
@ -94,11 +93,10 @@ namespace Volo.CmsKit.Tags
var tag = await _tagRepository.GetAsync(type, name); var tag = await _tagRepository.GetAsync(type, name);
await _tagManager.UpdateAsync(tag.Id, newName); var updatedTag = await _tagManager.UpdateAsync(tag.Id, newName);
var updatedTag = await _tagRepository.GetAsync(type, newName);
updatedTag.Id.ShouldBe(tag.Id); updatedTag.Id.ShouldBe(tag.Id);
updatedTag.Name.ShouldBe(newName);
} }
[Fact] [Fact]
@ -112,15 +110,5 @@ namespace Volo.CmsKit.Tags
Should.Throw<Exception>(async () => await _tagManager.UpdateAsync(tag.Id, newName)); Should.Throw<Exception>(async () => await _tagManager.UpdateAsync(tag.Id, newName));
} }
[Fact]
public async Task ShouldGetTagDefinitionsProperly_WithoutParameter()
{
var definitions = await _tagManager.GetTagDefinitionsAsync();
definitions.ShouldNotBeNull();
definitions.Count.ShouldBeGreaterThan(1);
definitions.ShouldContain(x => x.EntityType == _cmsKitTestData.TagDefinition_1_EntityType);
}
} }
} }

27
modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs

@ -61,5 +61,32 @@ namespace Volo.CmsKit.Blogs
result.ShouldBeFalse(); result.ShouldBeFalse();
} }
[Fact]
public async Task GetList_ShouldWorkProperly()
{
var list = await blogRepository.GetListAsync();
list.ShouldNotBeNull();
list.Count.ShouldBeGreaterThan(0);
}
[Fact]
public async Task GetCount_ShouldWorkProperly()
{
var count = await blogRepository.GetCountAsync();
count.ShouldBeGreaterThan(0);
}
[Fact]
public async Task SlugExistAsync_ShouldWorkProperly()
{
var exists = await blogRepository.SlugExistsAsync(testData.BlogSlug);
var notExists = await blogRepository.SlugExistsAsync("not-existing-blog-slug");
exists.ShouldBeTrue();
notExists.ShouldBeFalse();
}
} }
} }

45
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

@ -34,8 +34,9 @@ namespace Volo.CmsKit
private readonly IRatingRepository _ratingRepository; private readonly IRatingRepository _ratingRepository;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly IContentRepository _contentRepository; private readonly IContentRepository _contentRepository;
private readonly IEntityTagManager _entityTagManager; private readonly EntityTagManager _entityTagManager;
private readonly ITagManager _tagManager; private readonly TagManager _tagManager;
private readonly ITagRepository _tagRepository;
private readonly IEntityTagRepository _entityTagRepository; private readonly IEntityTagRepository _entityTagRepository;
private readonly IPageRepository _pageRepository; private readonly IPageRepository _pageRepository;
private readonly IBlogRepository _blogRepository; private readonly IBlogRepository _blogRepository;
@ -46,6 +47,7 @@ namespace Volo.CmsKit
private readonly IOptions<CmsKitTagOptions> _tagOptions; private readonly IOptions<CmsKitTagOptions> _tagOptions;
private readonly IMediaDescriptorRepository _mediaDescriptorRepository; private readonly IMediaDescriptorRepository _mediaDescriptorRepository;
private readonly IBlobContainer<MediaContainer> _mediaBlobContainer; private readonly IBlobContainer<MediaContainer> _mediaBlobContainer;
private readonly BlogManager _blogManager;
public CmsKitDataSeedContributor( public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
@ -56,18 +58,20 @@ namespace Volo.CmsKit
IRatingRepository ratingRepository, IRatingRepository ratingRepository,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IContentRepository contentRepository, IContentRepository contentRepository,
ITagManager tagManager, TagManager tagManager,
ITagRepository tagRepository,
IEntityTagRepository entityTagRepository, IEntityTagRepository entityTagRepository,
IPageRepository pageRepository, IPageRepository pageRepository,
IBlogRepository blogRepository, IBlogRepository blogRepository,
IBlogPostRepository blogPostRepository, IBlogPostRepository blogPostRepository,
BlogPostManager blogPostmanager, BlogPostManager blogPostmanager,
IBlogFeatureRepository blogFeatureRepository, IBlogFeatureRepository blogFeatureRepository,
IEntityTagManager entityTagManager, EntityTagManager entityTagManager,
IOptions<CmsKitOptions> options, IOptions<CmsKitOptions> options,
IOptions<CmsKitTagOptions> tagOptions, IOptions<CmsKitTagOptions> tagOptions,
IMediaDescriptorRepository mediaDescriptorRepository, IMediaDescriptorRepository mediaDescriptorRepository,
IBlobContainer<MediaContainer> mediaBlobContainer) IBlobContainer<MediaContainer> mediaBlobContainer,
BlogManager blogManager)
{ {
_guidGenerator = guidGenerator; _guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository; _cmsUserRepository = cmsUserRepository;
@ -78,6 +82,7 @@ namespace Volo.CmsKit
_currentTenant = currentTenant; _currentTenant = currentTenant;
_contentRepository = contentRepository; _contentRepository = contentRepository;
_tagManager = tagManager; _tagManager = tagManager;
_tagRepository = tagRepository;
_entityTagManager = entityTagManager; _entityTagManager = entityTagManager;
_entityTagRepository = entityTagRepository; _entityTagRepository = entityTagRepository;
_pageRepository = pageRepository; _pageRepository = pageRepository;
@ -89,6 +94,7 @@ namespace Volo.CmsKit
_tagOptions = tagOptions; _tagOptions = tagOptions;
_mediaDescriptorRepository = mediaDescriptorRepository; _mediaDescriptorRepository = mediaDescriptorRepository;
_mediaBlobContainer = mediaBlobContainer; _mediaBlobContainer = mediaBlobContainer;
_blogManager = blogManager;
} }
public async Task SeedAsync(DataSeedContext context) public async Task SeedAsync(DataSeedContext context)
@ -291,24 +297,40 @@ namespace Volo.CmsKit
private async Task SeedTagsAsync() private async Task SeedTagsAsync()
{ {
var created1 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_1, _cmsKitTestData.EntityType1, _cmsKitTestData.TagName_1); var created1 = await _tagRepository.InsertAsync(
await _tagManager.CreateAsync(
_cmsKitTestData.TagId_1,
_cmsKitTestData.EntityType1,
_cmsKitTestData.TagName_1));
await _entityTagManager.AddTagToEntityAsync(created1.Id, created1.EntityType, _cmsKitTestData.EntityId1); await _entityTagManager.AddTagToEntityAsync(created1.Id, created1.EntityType, _cmsKitTestData.EntityId1);
var created2 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_2, _cmsKitTestData.EntityType2, _cmsKitTestData.TagName_2); var created2 = await _tagRepository.InsertAsync(
await _tagManager.CreateAsync(
_cmsKitTestData.TagId_2,
_cmsKitTestData.EntityType2,
_cmsKitTestData.TagName_2));
await _entityTagManager.AddTagToEntityAsync(created2.Id, created2.EntityType, _cmsKitTestData.EntityId2); await _entityTagManager.AddTagToEntityAsync(created2.Id, created2.EntityType, _cmsKitTestData.EntityId2);
foreach (var tag in _cmsKitTestData.Content_1_Tags) foreach (var tag in _cmsKitTestData.Content_1_Tags)
{ {
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_1_EntityType, tag); var tagEntity = await _tagRepository.InsertAsync(
await _tagManager.CreateAsync(
_guidGenerator.Create(),
_cmsKitTestData.Content_1_EntityType,
tag));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId); await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId);
} }
foreach (var tag in _cmsKitTestData.Content_2_Tags) foreach (var tag in _cmsKitTestData.Content_2_Tags)
{ {
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_2_EntityType, tag); var tagEntity = await _tagRepository.InsertAsync(
await _tagManager.CreateAsync(
_guidGenerator.Create(),
_cmsKitTestData.Content_2_EntityType,
tag));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_2_EntityType, _cmsKitTestData.Content_2_EntityId); await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_2_EntityType, _cmsKitTestData.Content_2_EntityId);
} }
@ -331,7 +353,10 @@ namespace Volo.CmsKit
private async Task SeedBlogsAsync() private async Task SeedBlogsAsync()
{ {
var blog = await _blogRepository.InsertAsync(new Blog(_cmsKitTestData.Blog_Id, _cmsKitTestData.BlogName, _cmsKitTestData.BlogSlug), autoSave: true); var blog = await _blogRepository.InsertAsync(
await _blogManager.CreateAsync(_cmsKitTestData.BlogName, _cmsKitTestData.BlogSlug));
_cmsKitTestData.Blog_Id = blog.Id;
var author = await _cmsUserRepository.GetAsync(_cmsKitTestData.User1Id); var author = await _cmsUserRepository.GetAsync(_cmsKitTestData.User1Id);

2
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs

@ -73,7 +73,7 @@ namespace Volo.CmsKit
public string TagName_2 => "News"; public string TagName_2 => "News";
public Guid Blog_Id { get; } = Guid.NewGuid(); public Guid Blog_Id { get; set; } = Guid.NewGuid();
public string BlogName => "Cms Blog"; public string BlogName => "Cms Blog";

2
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -126,7 +126,7 @@
@if (Model.LanguageSelectListItems.Count > 1) @if (Model.LanguageSelectListItems.Count > 1)
{ {
<div class="col-5 @(Model.VersionSelectItems.Any()?"pl-0":"")"> <div class="@(Model.VersionSelectItems.Any()? "pl-0 col-5" : "col")">
<div class="docs-version docs-language @(Model.VersionSelectItems.Any()?"pl-1":"")"> <div class="docs-version docs-language @(Model.VersionSelectItems.Any()?"pl-1":"")">
<div class="version-select"> <div class="version-select">
<div class="input-group"> <div class="input-group">

20
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSecurityStampValidator.cs

@ -4,29 +4,41 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity.AspNetCore
{ {
public class AbpSecurityStampValidator : SecurityStampValidator<IdentityUser> public class AbpSecurityStampValidator : SecurityStampValidator<IdentityUser>
{ {
protected ITenantConfigurationProvider TenantConfigurationProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
public AbpSecurityStampValidator( public AbpSecurityStampValidator(
IOptions<SecurityStampValidatorOptions> options, IOptions<SecurityStampValidatorOptions> options,
SignInManager<IdentityUser> signInManager, SignInManager<IdentityUser> signInManager,
ISystemClock systemClock, ISystemClock systemClock,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory,
ITenantConfigurationProvider tenantConfigurationProvider,
ICurrentTenant currentTenant)
: base( : base(
options, options,
signInManager, signInManager,
systemClock, systemClock,
loggerFactory) loggerFactory)
{ {
TenantConfigurationProvider = tenantConfigurationProvider;
CurrentTenant = currentTenant;
} }
[UnitOfWork] [UnitOfWork]
public override Task ValidateAsync(CookieValidatePrincipalContext context) public override async Task ValidateAsync(CookieValidatePrincipalContext context)
{ {
return base.ValidateAsync(context); var tenant = await TenantConfigurationProvider.GetAsync(saveResolveResult: false);
using (CurrentTenant.Change(tenant?.Id, tenant?.Name))
{
await base.ValidateAsync(context);
}
} }
} }
} }

77
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs

@ -53,57 +53,54 @@ namespace Volo.Abp.Identity
{ {
await IdentityOptions.SetAsync(); await IdentityOptions.SetAsync();
using (IdentityOptions.Value.Password.ClearRequirements()) var result = new IdentityDataSeedResult();
//"admin" user
const string adminUserName = "admin";
var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
LookupNormalizer.NormalizeName(adminUserName)
);
if (adminUser != null)
{ {
var result = new IdentityDataSeedResult(); return result;
//"admin" user }
const string adminUserName = "admin";
var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
LookupNormalizer.NormalizeName(adminUserName)
);
if (adminUser != null) adminUser = new IdentityUser(
{ GuidGenerator.Create(),
return result; adminUserName,
} adminEmail,
tenantId
)
{
Name = adminUserName
};
(await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors();
result.CreatedAdminUser = true;
adminUser = new IdentityUser( //"admin" role
const string adminRoleName = "admin";
var adminRole =
await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(adminRoleName));
if (adminRole == null)
{
adminRole = new IdentityRole(
GuidGenerator.Create(), GuidGenerator.Create(),
adminUserName, adminRoleName,
adminEmail,
tenantId tenantId
) )
{ {
Name = adminUserName IsStatic = true,
IsPublic = true
}; };
(await UserManager.CreateAsync(adminUser, adminPassword)).CheckErrors(); (await RoleManager.CreateAsync(adminRole)).CheckErrors();
result.CreatedAdminUser = true; result.CreatedAdminRole = true;
}
//"admin" role
const string adminRoleName = "admin";
var adminRole =
await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(adminRoleName));
if (adminRole == null)
{
adminRole = new IdentityRole(
GuidGenerator.Create(),
adminRoleName,
tenantId
)
{
IsStatic = true,
IsPublic = true
};
(await RoleManager.CreateAsync(adminRole)).CheckErrors();
result.CreatedAdminRole = true;
}
(await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors(); (await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
return result; return result;
}
} }
} }
} }

11
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs

@ -60,6 +60,17 @@ namespace Volo.Abp.Identity
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
} }
public virtual async Task<IdentityResult> CreateAsync(IdentityUser user, string password, bool validatePassword)
{
var result = await UpdatePasswordHash(user, password, validatePassword);
if (!result.Succeeded)
{
return result;
}
return await CreateAsync(user);
}
public virtual async Task<IdentityUser> GetByIdAsync(Guid id) public virtual async Task<IdentityUser> GetByIdAsync(Guid id)
{ {
var user = await Store.FindByIdAsync(id.ToString(), CancellationToken); var user = await Store.FindByIdAsync(id.ToString(), CancellationToken);

35
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/PasswordOptionsExtensions.cs

@ -1,35 +0,0 @@
using System;
using Microsoft.AspNetCore.Identity;
namespace Volo.Abp.Identity
{
public static class PasswordOptionsExtensions
{
public static IDisposable ClearRequirements(this PasswordOptions options)
{
var oldRequireDigit = options.RequireDigit;
var oldRequiredLength = options.RequiredLength;
var oldRequireLowercase = options.RequireLowercase;
var oldRequireUppercase = options.RequireUppercase;
var oldRequiredUniqueChars = options.RequiredUniqueChars;
var oldRequireNonAlphanumeric = options.RequireNonAlphanumeric;
options.RequireDigit = false;
options.RequiredLength = 1;
options.RequireLowercase = false;
options.RequireUppercase = false;
options.RequiredUniqueChars = 1;
options.RequireNonAlphanumeric = false;
return new DisposeAction(() =>
{
options.RequireDigit = oldRequireDigit;
options.RequiredLength = oldRequiredLength;
options.RequireLowercase = oldRequireLowercase;
options.RequireUppercase = oldRequireUppercase;
options.RequiredUniqueChars = oldRequiredUniqueChars;
options.RequireNonAlphanumeric = oldRequireNonAlphanumeric;
});
}
}
}

1
nupkg/common.ps1

@ -126,6 +126,7 @@ $projects = (
"framework/src/Volo.Abp.Serialization", "framework/src/Volo.Abp.Serialization",
"framework/src/Volo.Abp.Settings", "framework/src/Volo.Abp.Settings",
"framework/src/Volo.Abp.Sms", "framework/src/Volo.Abp.Sms",
"framework/src/Volo.Abp.Sms.Aliyun",
"framework/src/Volo.Abp.Specifications", "framework/src/Volo.Abp.Specifications",
"framework/src/Volo.Abp.TestBase", "framework/src/Volo.Abp.TestBase",
"framework/src/Volo.Abp.TextTemplating", "framework/src/Volo.Abp.TextTemplating",

Loading…
Cancel
Save