mirror of https://github.com/abpframework/abp.git
256 changed files with 10059 additions and 1055 deletions
@ -0,0 +1,30 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.Primitives; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Security |
|||
{ |
|||
public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency |
|||
{ |
|||
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
|||
{ |
|||
/*X-Content-Type-Options header tells the browser to not try and “guess” what a mimetype of a resource might be, and to just take what mimetype the server has returned as fact.*/ |
|||
AddHeaderIfNotExists(context, "X-Content-Type-Options", "nosniff"); |
|||
|
|||
/*X-XSS-Protection is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks*/ |
|||
AddHeaderIfNotExists(context, "X-XSS-Protection", "1; mode=block"); |
|||
|
|||
/*The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object>. SAMEORIGIN makes it being displayed in a frame on the same origin as the page itself. The spec leaves it up to browser vendors to decide whether this option applies to the top level, the parent, or the whole chain*/ |
|||
AddHeaderIfNotExists(context, "X-Frame-Options", "SAMEORIGIN"); |
|||
|
|||
await next.Invoke(context); |
|||
} |
|||
|
|||
protected virtual void AddHeaderIfNotExists(HttpContext context, string key, string value) |
|||
{ |
|||
context.Response.Headers.AddIfNotContains(new KeyValuePair<string, StringValues>(key, value)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
namespace Volo.Abp.BlobStoring |
|||
{ |
|||
public class BlobNormalizeNaming |
|||
{ |
|||
public string ContainerName { get; } |
|||
|
|||
public string BlobName { get; } |
|||
|
|||
public BlobNormalizeNaming(string containerName, string blobName) |
|||
{ |
|||
ContainerName = containerName; |
|||
BlobName = blobName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.BlobStoring |
|||
{ |
|||
public class BlobNormalizeNamingService : IBlobNormalizeNamingService, ITransientDependency |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public BlobNormalizeNamingService(IServiceProvider serviceProvider) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
} |
|||
|
|||
public BlobNormalizeNaming NormalizeNaming( |
|||
BlobContainerConfiguration configuration, |
|||
string containerName, |
|||
string blobName) |
|||
{ |
|||
|
|||
if (!configuration.NamingNormalizers.Any()) |
|||
{ |
|||
return new BlobNormalizeNaming(containerName, blobName); |
|||
} |
|||
|
|||
using (var scope = ServiceProvider.CreateScope()) |
|||
{ |
|||
foreach (var normalizerType in configuration.NamingNormalizers) |
|||
{ |
|||
var normalizer = scope.ServiceProvider |
|||
.GetRequiredService(normalizerType) |
|||
.As<IBlobNamingNormalizer>(); |
|||
|
|||
containerName = containerName.IsNullOrWhiteSpace()? containerName: normalizer.NormalizeContainerName(containerName); |
|||
blobName = blobName.IsNullOrWhiteSpace()? blobName: normalizer.NormalizeBlobName(blobName); |
|||
} |
|||
|
|||
return new BlobNormalizeNaming(containerName, blobName); |
|||
} |
|||
} |
|||
|
|||
public string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName) |
|||
{ |
|||
if (!configuration.NamingNormalizers.Any()) |
|||
{ |
|||
return containerName; |
|||
} |
|||
|
|||
return NormalizeNaming(configuration, containerName, null).ContainerName; |
|||
} |
|||
|
|||
public string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName) |
|||
{ |
|||
if (!configuration.NamingNormalizers.Any()) |
|||
{ |
|||
return blobName; |
|||
} |
|||
|
|||
return NormalizeNaming(configuration, null, blobName).BlobName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace Volo.Abp.BlobStoring |
|||
{ |
|||
public interface IBlobNormalizeNamingService |
|||
{ |
|||
BlobNormalizeNaming NormalizeNaming(BlobContainerConfiguration configuration, string containerName, string blobName); |
|||
|
|||
string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName); |
|||
|
|||
string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName); |
|||
} |
|||
} |
|||
@ -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()); |
|||
} |
|||
} |
|||
} |
|||
@ -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,143 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Shouldly; |
|||
using System; |
|||
using System.Reflection; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class AbpServiceConvention_Tests : AspNetCoreMvcTestBase |
|||
{ |
|||
private readonly IConventionalRouteBuilder _conventionalRouteBuilder; |
|||
private readonly IOptions<AbpAspNetCoreMvcOptions> _options; |
|||
|
|||
public AbpServiceConvention_Tests() |
|||
{ |
|||
_conventionalRouteBuilder = GetRequiredService<IConventionalRouteBuilder>(); |
|||
_options = GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Not_Remove_Derived_Controller_If_Not_Expose_Service() |
|||
{ |
|||
// Arrange
|
|||
var applicationModel = new ApplicationModel(); |
|||
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(baseControllerModel); |
|||
|
|||
var derivedControllerModel = new ControllerModel(typeof(DerivedController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(derivedControllerModel); |
|||
|
|||
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder); |
|||
|
|||
// Act
|
|||
abpServiceConvention.Apply(applicationModel); |
|||
|
|||
// Assert
|
|||
applicationModel.Controllers.ShouldContain(baseControllerModel); |
|||
applicationModel.Controllers.ShouldContain(derivedControllerModel); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Remove_Exposed_Controller_If_Expose_Self() |
|||
{ |
|||
// Arrange
|
|||
var applicationModel = new ApplicationModel(); |
|||
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(baseControllerModel); |
|||
|
|||
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceIncludeSelfDerivedController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(derivedControllerModel); |
|||
|
|||
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder); |
|||
|
|||
// Act
|
|||
abpServiceConvention.Apply(applicationModel); |
|||
|
|||
// Assert
|
|||
applicationModel.Controllers.ShouldNotContain(baseControllerModel); |
|||
applicationModel.Controllers.ShouldContain(derivedControllerModel); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Not_Remove_Derived_Controller_If_No_Base_Controller_Model() |
|||
{ |
|||
// Arrange
|
|||
var applicationModel = new ApplicationModel(); |
|||
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(derivedControllerModel); |
|||
|
|||
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder); |
|||
|
|||
// Act
|
|||
abpServiceConvention.Apply(applicationModel); |
|||
|
|||
// Assert
|
|||
applicationModel.Controllers.ShouldContain(derivedControllerModel); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Remove_Derived_Controller_If_Expose_Service() |
|||
{ |
|||
// Arrange
|
|||
var applicationModel = new ApplicationModel(); |
|||
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(baseControllerModel); |
|||
|
|||
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>()) |
|||
{ |
|||
Application = applicationModel |
|||
}; |
|||
applicationModel.Controllers.Add(derivedControllerModel); |
|||
|
|||
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder); |
|||
|
|||
// Act
|
|||
abpServiceConvention.Apply(applicationModel); |
|||
|
|||
// Assert
|
|||
applicationModel.Controllers.ShouldContain(baseControllerModel); |
|||
applicationModel.Controllers.ShouldNotContain(derivedControllerModel); |
|||
} |
|||
} |
|||
|
|||
public class BaseController : Controller |
|||
{ |
|||
} |
|||
|
|||
public class DerivedController : BaseController |
|||
{ |
|||
} |
|||
|
|||
[ExposeServices(typeof(BaseController))] |
|||
public class ExposeServiceDerivedController : BaseController |
|||
{ |
|||
} |
|||
|
|||
[ExposeServices(typeof(BaseController), IncludeSelf = true)] |
|||
public class ExposeServiceIncludeSelfDerivedController : BaseController |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers |
|||
{ |
|||
public class SecurityHeadersTestController : AbpController |
|||
{ |
|||
public ActionResult Get() |
|||
{ |
|||
return Content("OK"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers |
|||
{ |
|||
public class SecurityHeadersTestController_Tests : AspNetCoreMvcTestBase |
|||
{ |
|||
[Fact] |
|||
public async Task SecurityHeaders_Should_Be_Added() |
|||
{ |
|||
var responseMessage = await GetResponseAsync("/SecurityHeadersTest/Get"); |
|||
responseMessage.Headers.ShouldContain(x => x.Key == "X-Content-Type-Options" & x.Value.First().ToString() == "nosniff"); |
|||
responseMessage.Headers.ShouldContain(x => x.Key == "X-XSS-Protection" & x.Value.First().ToString() == "1; mode=block"); |
|||
responseMessage.Headers.ShouldContain(x => x.Key == "X-Frame-Options" & x.Value.First().ToString() == "SAMEORIGIN"); |
|||
} |
|||
} |
|||
} |
|||
@ -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>" |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Page_Remove_Description : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "Description", |
|||
table: "CmsPages"); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "Description", |
|||
table: "CmsPages", |
|||
type: "nvarchar(512)", |
|||
maxLength: 512, |
|||
nullable: true); |
|||
} |
|||
} |
|||
} |
|||
@ -1,19 +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; } |
|||
} |
|||
} |
|||
|
|||
@ -1,11 +1,14 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
[Serializable] |
|||
public class BlogFeatureInputDto |
|||
{ |
|||
[Required] |
|||
public string FeatureName { get; set; } |
|||
|
|||
public bool IsEnabled { 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; } |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue