CmsKit - Fix merge conflict from dev to blogs-refactorings

pull/7845/head
enisn 5 years ago
commit fb8fcefb4c

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

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

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

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

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

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

@ -361,6 +361,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Tests", "test
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}"
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
GlobalSection(SolutionConfigurationPlatforms) = preSolution
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}.Release|Any CPU.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1257,6 +1269,8 @@ Global
{00D07595-993C-40FC-BD90-0DD6331414D3} = {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}
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

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

@ -2,6 +2,9 @@
using System.Linq;
using System.Reflection;
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.AspNetCore.Mvc.Conventions;
@ -13,6 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public Func<MethodInfo, string> ActionNameGenerator { get; set; }
public Func<ApiParameterDescription, string> ApiParameterNameGenerator { get; set; }
public AspNetCoreApiDescriptionModelProviderOptions()
{
ControllerNameGenerator = (controllerType, setting) =>
@ -52,6 +57,28 @@ namespace Volo.Abp.AspNetCore.Mvc
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;
};
}
}
}

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

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

@ -147,19 +147,34 @@ namespace Volo.Abp.Cli.Commands
}
var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
if (!createSolutionFolder)
{
Logger.LogInformation("Create Solution Folder: no");
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
var outputFolderRoot =
outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
SolutionName solutionName;
if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
{
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);
@ -176,7 +191,7 @@ namespace Volo.Abp.Cli.Commands
var result = await TemplateProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(projectName),
solutionName,
template,
version,
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)
{
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)
{
if (commandLineArgs.Options.ContainsKey("no-ui"))
{
return UiFramework.None;
}
var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
switch (optionValue)
{

@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
@ -25,7 +26,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var localVoloRepoPath = context.BuildArgs.VoloGitHubLocalRepositoryPath;
new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
localAbpRepoPath,
localVoloRepoPath
@ -41,7 +42,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
}
new ProjectReferenceReplacer.NugetReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
nugetPackageVersion
).Run();
@ -70,13 +71,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private abstract class ProjectReferenceReplacer
{
private readonly List<FileEntry> _entries;
private readonly bool _isMicroserviceServiceTemplate;
private readonly string _projectName;
protected ProjectReferenceReplacer(
List<FileEntry> entries,
ProjectBuildContext context,
string projectName)
{
_entries = entries;
_entries = context.Files;
_isMicroserviceServiceTemplate = MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.Template?.Name);
_projectName = projectName;
}
@ -113,14 +116,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
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
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;
newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
XmlNode newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
oldNode.ParentNode.ReplaceChild(newNode, oldNode);
}
@ -145,8 +149,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string projectName, string nugetPackageVersion)
: base(entries, projectName)
public NugetReferenceReplacer(ProjectBuildContext context, string projectName, string nugetPackageVersion)
: base(context, projectName)
{
_nugetPackageVersion = nugetPackageVersion;
}
@ -183,8 +187,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private readonly string _gitHubAbpLocalRepositoryPath;
private readonly string _gitHubVoloLocalRepositoryPath;
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(entries, projectName)
public LocalProjectPathReferenceReplacer(ProjectBuildContext context, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(context, projectName)
{
_gitHubAbpLocalRepositoryPath = gitHubAbpLocalRepositoryPath;
_gitHubVoloLocalRepositoryPath = gitHubVoloLocalRepositoryPath;

@ -85,11 +85,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context)
{
if (_solutionFilePath == null)
{
_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)
{

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

@ -33,7 +33,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
}
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());
}

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

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

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

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

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

@ -34,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification
}
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectToAngularJsonAsync(angularPath, projects);
}
catch (Exception e)
@ -93,6 +94,61 @@ namespace Volo.Abp.Cli.ProjectModification
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,
List<string> projects)
{
@ -105,7 +161,8 @@ namespace Volo.Abp.Cli.ProjectModification
{
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\\"))
.Select(p => p.RemovePreFix(angularPath).Replace("\\", "/").RemovePreFix("/"));
@ -171,8 +228,10 @@ namespace Volo.Abp.Cli.ProjectModification
{
continue;
}
Directory.Move(folderUnderProject, Path.Combine(folder, Path.GetFileName(folderUnderProject)));
}
projectsInFolder = Directory.GetDirectories(folder);
}

@ -10,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
public string Name { get; set; }
public string JsonName { get; set; }
public string Type { 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
{
Name = name,
JsonName = jsonName,
NameOnMethod = nameOnMethod,
Type = type != null ? TypeHelper.GetFullNameHandlingNullableAndGenerics(type) : null,
TypeSimple = type != null ? ApiTypeNameHelper.GetSimpleTypeName(type) : null,

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

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.Http.ProxyScripting.Configuration
{
@ -7,9 +8,30 @@ namespace Volo.Abp.Http.ProxyScripting.Configuration
{
public IDictionary<string, Type> Generators { get; }
public static Func<PropertyInfo, string> PropertyNameGenerator { get; set; }
public AbpApiProxyScriptingOptions()
{
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;
};
}
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,10 +1,8 @@
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Application.Dtos;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.GlobalFeatures;
@ -14,24 +12,63 @@ namespace Volo.CmsKit.Admin.Blogs
{
[RequiresGlobalFeature(typeof(BlogsFeature))]
[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;
GetPolicyName = CmsKitAdminPermissions.Blogs.Default;
CreatePolicyName = CmsKitAdminPermissions.Blogs.Create;
UpdatePolicyName = CmsKitAdminPermissions.Blogs.Update;
DeletePolicyName = CmsKitAdminPermissions.Blogs.Delete;
BlogRepository = blogRepository;
BlogManager = blogManager;
}
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 queryable
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
x => x.Name.ToLower().Contains(input.Filter));
return BlogRepository.DeleteAsync(id);
}
}
}

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

@ -8,15 +8,15 @@ namespace Volo.CmsKit.Admin.Tags
public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService
{
protected ITagDefinitionStore TagDefinitionStore { get; }
protected IEntityTagManager EntityTagManager { get; }
protected ITagManager TagManager { get; }
protected EntityTagManager EntityTagManager { get; }
protected TagManager TagManager { get; }
protected ITagRepository TagRepository { get; }
protected IEntityTagRepository EntityTagRepository { get; }
public EntityTagAdminAppService(
ITagDefinitionStore tagDefinitionStore,
IEntityTagManager entityTagManager,
ITagManager tagManager,
EntityTagManager entityTagManager,
TagManager tagManager,
ITagRepository tagRepository,
IEntityTagRepository entityTagRepository)
{
@ -29,11 +29,11 @@ namespace Volo.CmsKit.Admin.Tags
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);
var tag = await TagManager.GetOrAddAsync(input.EntityType, input.TagName, CurrentTenant?.Id);
var tag = await TagManager.GetOrAddAsync(input.EntityType, input.TagName);
await EntityTagManager.AddTagToEntityAsync(
tag.Id,
@ -44,7 +44,7 @@ namespace Volo.CmsKit.Admin.Tags
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);
@ -57,24 +57,11 @@ namespace Volo.CmsKit.Admin.Tags
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);
var existingTags =
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);
}
await EntityTagManager.SetEntityTagsAsync(input.EntityType, input.EntityId, input.Tags);
}
}
}
}

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

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

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

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

@ -3,6 +3,7 @@
"texts": {
"CmsKit:0002": "Content already exists!",
"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:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Page:0001": "The given url ({0}) already exists.",

@ -9,17 +9,6 @@ namespace Volo.CmsKit.Blogs
{
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]
public virtual string Name { get; protected set; }
@ -27,15 +16,22 @@ namespace Volo.CmsKit.Blogs
public virtual string Slug { 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)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), maxLength: BlogConsts.MaxNameLength);
Name = Check.NotNullOrWhiteSpace(name, nameof(name), BlogConsts.MaxNameLength);
}
public virtual void SetSlug(string slug)
{
Check.NotNullOrWhiteSpace(slug, nameof(slug), maxLength: BlogConsts.MaxNameLength);
Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogConsts.MaxNameLength);
Slug = slug.NormalizeSlug();
}

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

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

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

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,7 +8,23 @@ namespace Volo.CmsKit.Blogs
{
public interface IBlogRepository : IBasicRepository<Blog, Guid>
{
public Task<Blog> GetBySlugAsync(string slug, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default);
Task<List<Blog>> GetListAsync(
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);
}
}

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

@ -3,9 +3,9 @@ using System.Linq;
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))
{

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

@ -24,7 +24,7 @@ namespace Volo.CmsKit.Tags
/// <param name="entityType">EntityType to get definition.</param>
/// <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>
public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType)
public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));

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

@ -1,22 +1,30 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
namespace Volo.CmsKit.Tags
{
public class EntityTagManager : DomainService, IEntityTagManager
public class EntityTagManager : DomainService
{
protected IEntityTagRepository EntityTagRepository { get; }
protected ITagRepository TagRepository { get; }
protected ITagDefinitionStore TagDefinitionStore { get; }
protected TagManager TagManager { get; }
public EntityTagManager(
IEntityTagRepository entityTagRepository,
ITagDefinitionStore tagDefinitionStore)
ITagRepository tagRepository,
ITagDefinitionStore tagDefinitionStore,
TagManager tagManager)
{
EntityTagRepository = entityTagRepository;
TagRepository = tagRepository;
TagDefinitionStore = tagDefinitionStore;
TagManager = tagManager;
}
public virtual async Task<EntityTag> AddTagToEntityAsync(
@ -45,5 +53,23 @@ namespace Volo.CmsKit.Tags
var entityTag = await EntityTagRepository.FindAsync(tagId, entityId, tenantId, 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);
}
}
}
}

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

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

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

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

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

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

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

@ -1,9 +1,11 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Security.Cryptography.X509Certificates;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.Domain.Repositories.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));
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));
}
}
}

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

@ -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.Tasks;
using JetBrains.Annotations;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Repositories.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(
await GetQueryableAsync(),
x => x.Id == blogId,
cancellationToken);
var token = GetCancellationToken(cancellationToken);
return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Id == id, token);
}
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));
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));
}
}
}

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

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

@ -48,5 +48,15 @@ namespace Volo.CmsKit.Tags
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);
}
}
}

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

@ -1,4 +1,5 @@
using Shouldly;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Guids;
@ -9,14 +10,14 @@ namespace Volo.CmsKit.Tags
public class EntityTagManager_Tests : CmsKitDomainTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly IEntityTagManager _entityTagManager;
private readonly EntityTagManager _entityTagManager;
private readonly ITagRepository _tagRepository;
private readonly IGuidGenerator _guidGenerator;
public EntityTagManager_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_entityTagManager = GetRequiredService<IEntityTagManager>();
_entityTagManager = GetRequiredService<EntityTagManager>();
_tagRepository = GetRequiredService<ITagRepository>();
_guidGenerator = GetRequiredService<IGuidGenerator>();
}
@ -56,5 +57,54 @@ namespace Volo.CmsKit.Tags
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));
}
}
}

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

@ -61,5 +61,32 @@ namespace Volo.CmsKit.Blogs
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();
}
}
}

@ -34,8 +34,9 @@ namespace Volo.CmsKit
private readonly IRatingRepository _ratingRepository;
private readonly ICurrentTenant _currentTenant;
private readonly IContentRepository _contentRepository;
private readonly IEntityTagManager _entityTagManager;
private readonly ITagManager _tagManager;
private readonly EntityTagManager _entityTagManager;
private readonly TagManager _tagManager;
private readonly ITagRepository _tagRepository;
private readonly IEntityTagRepository _entityTagRepository;
private readonly IPageRepository _pageRepository;
private readonly IBlogRepository _blogRepository;
@ -46,6 +47,7 @@ namespace Volo.CmsKit
private readonly IOptions<CmsKitTagOptions> _tagOptions;
private readonly IMediaDescriptorRepository _mediaDescriptorRepository;
private readonly IBlobContainer<MediaContainer> _mediaBlobContainer;
private readonly BlogManager _blogManager;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
@ -56,18 +58,20 @@ namespace Volo.CmsKit
IRatingRepository ratingRepository,
ICurrentTenant currentTenant,
IContentRepository contentRepository,
ITagManager tagManager,
TagManager tagManager,
ITagRepository tagRepository,
IEntityTagRepository entityTagRepository,
IPageRepository pageRepository,
IBlogRepository blogRepository,
IBlogPostRepository blogPostRepository,
BlogPostManager blogPostmanager,
IBlogFeatureRepository blogFeatureRepository,
IEntityTagManager entityTagManager,
EntityTagManager entityTagManager,
IOptions<CmsKitOptions> options,
IOptions<CmsKitTagOptions> tagOptions,
IMediaDescriptorRepository mediaDescriptorRepository,
IBlobContainer<MediaContainer> mediaBlobContainer)
IBlobContainer<MediaContainer> mediaBlobContainer,
BlogManager blogManager)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -78,6 +82,7 @@ namespace Volo.CmsKit
_currentTenant = currentTenant;
_contentRepository = contentRepository;
_tagManager = tagManager;
_tagRepository = tagRepository;
_entityTagManager = entityTagManager;
_entityTagRepository = entityTagRepository;
_pageRepository = pageRepository;
@ -89,6 +94,7 @@ namespace Volo.CmsKit
_tagOptions = tagOptions;
_mediaDescriptorRepository = mediaDescriptorRepository;
_mediaBlobContainer = mediaBlobContainer;
_blogManager = blogManager;
}
public async Task SeedAsync(DataSeedContext context)
@ -291,24 +297,40 @@ namespace Volo.CmsKit
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);
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);
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);
}
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);
}
@ -331,7 +353,10 @@ namespace Volo.CmsKit
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);

@ -73,7 +73,7 @@ namespace Volo.CmsKit
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";

@ -126,7 +126,7 @@
@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="version-select">
<div class="input-group">

@ -4,29 +4,41 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace Volo.Abp.Identity.AspNetCore
{
public class AbpSecurityStampValidator : SecurityStampValidator<IdentityUser>
{
protected ITenantConfigurationProvider TenantConfigurationProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
public AbpSecurityStampValidator(
IOptions<SecurityStampValidatorOptions> options,
SignInManager<IdentityUser> signInManager,
ISystemClock systemClock,
ILoggerFactory loggerFactory)
ILoggerFactory loggerFactory,
ITenantConfigurationProvider tenantConfigurationProvider,
ICurrentTenant currentTenant)
: base(
options,
options,
signInManager,
systemClock,
loggerFactory)
{
TenantConfigurationProvider = tenantConfigurationProvider;
CurrentTenant = currentTenant;
}
[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);
}
}
}
}

@ -53,57 +53,54 @@ namespace Volo.Abp.Identity
{
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();
//"admin" user
const string adminUserName = "admin";
var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
LookupNormalizer.NormalizeName(adminUserName)
);
return result;
}
if (adminUser != null)
{
return result;
}
adminUser = new IdentityUser(
GuidGenerator.Create(),
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(),
adminUserName,
adminEmail,
adminRoleName,
tenantId
)
{
Name = adminUserName
IsStatic = true,
IsPublic = true
};
(await UserManager.CreateAsync(adminUser, adminPassword)).CheckErrors();
result.CreatedAdminUser = 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 RoleManager.CreateAsync(adminRole)).CheckErrors();
result.CreatedAdminRole = true;
}
(await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
(await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
return result;
}
return result;
}
}
}

@ -60,6 +60,17 @@ namespace Volo.Abp.Identity
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)
{
var user = await Store.FindByIdAsync(id.ToString(), CancellationToken);

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

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

Loading…
Cancel
Save