BasicAuth bezieht Realm aus dem Validator. DNS Resolve für E-Mail Validierung geändert. Moq-Package hinzugefügt.
This commit is contained in:
@@ -12,19 +12,16 @@ namespace AMWD.Common.AspNetCore.BasicAuthentication
|
||||
public class BasicAuthenticationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate next;
|
||||
private readonly string realm;
|
||||
private readonly IBasicAuthenticationValidator validator;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BasicAuthenticationMiddleware"/> class.
|
||||
/// </summary>
|
||||
/// <param name="next">The following delegate in the process chain.</param>
|
||||
/// <param name="realm">The realm to display when requesting for credentials.</param>
|
||||
/// <param name="validator">A basic authentication validator.</param>
|
||||
public BasicAuthenticationMiddleware(RequestDelegate next, string realm, IBasicAuthenticationValidator validator)
|
||||
public BasicAuthenticationMiddleware(RequestDelegate next, IBasicAuthenticationValidator validator)
|
||||
{
|
||||
this.next = next;
|
||||
this.realm = realm;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
@@ -53,10 +50,8 @@ namespace AMWD.Common.AspNetCore.BasicAuthentication
|
||||
}
|
||||
|
||||
httpContext.Response.Headers["WWW-Authenticate"] = "Basic";
|
||||
if (!string.IsNullOrWhiteSpace(realm))
|
||||
{
|
||||
httpContext.Response.Headers["WWW-Authenticate"] += $" realm=\"{realm}\"";
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(validator.Realm))
|
||||
httpContext.Response.Headers["WWW-Authenticate"] += $" realm=\"{validator.Realm}\"";
|
||||
|
||||
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace AMWD.Common.AspNetCore.BasicAuthentication
|
||||
/// </summary>
|
||||
public interface IBasicAuthenticationValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the realm to use when requesting authentication.
|
||||
/// </summary>
|
||||
string Realm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a username and password for Basic Authentication.
|
||||
/// </summary>
|
||||
|
||||
@@ -66,19 +66,24 @@ namespace Microsoft.EntityFrameworkCore
|
||||
return DatabaseProvider.SQLite;
|
||||
if (provider.Contains("sqlclient", StringComparison.OrdinalIgnoreCase))
|
||||
return DatabaseProvider.SQLServer;
|
||||
if (provider.Contains("inmemory", StringComparison.OrdinalIgnoreCase))
|
||||
return DatabaseProvider.InMemory;
|
||||
|
||||
throw new DatabaseProviderException($"The database provider '{provider}' is unknown");
|
||||
}
|
||||
|
||||
private static async Task<bool> CreateMigrationsTable(this DbConnection connection, DatabaseMigrationOptions options, CancellationToken cancellationToken)
|
||||
{
|
||||
if (connection.GetProviderType() == DatabaseProvider.InMemory)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
using var command = connection.CreateCommand();
|
||||
|
||||
#pragma warning disable CS8524 // missing default case
|
||||
#pragma warning disable CS8509 // ignore missing cases
|
||||
command.CommandText = connection.GetProviderType() switch
|
||||
#pragma warning restore CS8524 // missing default case
|
||||
#pragma warning restore CS8509 // ignore missing cases
|
||||
{
|
||||
DatabaseProvider.MySQL => $@"CREATE TABLE IF NOT EXISTS `{options.MigrationsTableName}` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
@@ -135,6 +140,9 @@ END;"
|
||||
|
||||
private static async Task<bool> Migrate(this DbConnection connection, DatabaseMigrationOptions options, CancellationToken cancellationToken)
|
||||
{
|
||||
if (connection.GetProviderType() == DatabaseProvider.InMemory)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
List<string> availableMigrationFiles;
|
||||
@@ -279,7 +287,8 @@ END;"
|
||||
Oracle = 2,
|
||||
PostgreSQL = 3,
|
||||
SQLite = 4,
|
||||
SQLServer = 5
|
||||
SQLServer = 5,
|
||||
InMemory = 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@ namespace Microsoft.EntityFrameworkCore
|
||||
case "mssql":
|
||||
methodInfo = extensionType.GetMethod("UseSqlServer", new Type[] { typeof(DbContextOptionsBuilder), typeof(string), actionType });
|
||||
break;
|
||||
case "memory":
|
||||
case "inmemory":
|
||||
methodInfo = extensionType.GetMethod("UseInMemoryDatabase", new Type[] { typeof(DbContextOptionsBuilder), typeof(string), actionType });
|
||||
break;
|
||||
default:
|
||||
throw new DatabaseProviderException($"Unknown database provider: {provider}");
|
||||
}
|
||||
@@ -122,6 +126,10 @@ namespace Microsoft.EntityFrameworkCore
|
||||
case "mssql":
|
||||
builderType = Type.GetType("Microsoft.EntityFrameworkCore.Infrastructure.SqlServerDbContextOptionsBuilder, Microsoft.EntityFrameworkCore.SqlServer");
|
||||
break;
|
||||
case "memory":
|
||||
case "inmemory":
|
||||
builderType = Type.GetType("Microsoft.EntityFrameworkCore.Infrastructure.InMemoryDbContextOptionsBuilder, Microsoft.EntityFrameworkCore.InMemory");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown database provider: {provider}");
|
||||
}
|
||||
@@ -155,6 +163,10 @@ namespace Microsoft.EntityFrameworkCore
|
||||
case "mssql":
|
||||
extensionType = Type.GetType("Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions, Microsoft.EntityFrameworkCore.SqlServer");
|
||||
break;
|
||||
case "memory":
|
||||
case "inmemory":
|
||||
extensionType = Type.GetType("Microsoft.EntityFrameworkCore.InMemoryDbContextOptionsExtensions, Microsoft.EntityFrameworkCore.InMemory");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown database provider: {provider}");
|
||||
}
|
||||
@@ -219,6 +231,10 @@ namespace Microsoft.EntityFrameworkCore
|
||||
}
|
||||
cs.Add("Connect Timeout=15");
|
||||
break;
|
||||
case "memory":
|
||||
case "inmemory":
|
||||
cs.Add(configuration.GetValue("Name", provider));
|
||||
break;
|
||||
default:
|
||||
throw new DatabaseProviderException($"Unknown database provider: {provider}");
|
||||
}
|
||||
|
||||
46
AMWD.Common.Moq/AMWD.Common.Moq.csproj
Normal file
46
AMWD.Common.Moq/AMWD.Common.Moq.csproj
Normal file
@@ -0,0 +1,46 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
|
||||
<AssemblyName>AMWD.Common.Moq</AssemblyName>
|
||||
<RootNamespace>AMWD.Common.Moq</RootNamespace>
|
||||
<NrtRevisionFormat>{semvertag:master:+chash}{!:-dirty}</NrtRevisionFormat>
|
||||
|
||||
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
|
||||
<PackageId>AMWD.Common.Moq</PackageId>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageProjectUrl>https://wiki.am-wd.de/libs/common</PackageProjectUrl>
|
||||
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://git.am-wd.de/AM.WD/common.git</RepositoryUrl>
|
||||
|
||||
<Product>AM.WD Common Library for Moq</Product>
|
||||
<Description>Library with classes and extensions used frequently on AM.WD projects.</Description>
|
||||
<Company>AM.WD</Company>
|
||||
<Authors>Andreas Müller</Authors>
|
||||
<Copyright>© {copyright:2020-} AM.WD</Copyright>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../icon.png" Pack="true" PackagePath="/" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
130
AMWD.Common.Moq/HttpMessageHandlerMoq.cs
Normal file
130
AMWD.Common.Moq/HttpMessageHandlerMoq.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
|
||||
namespace AMWD.Common.Moq
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapps the <see cref="Mock{HttpMessageHandler}"/> including the setup.
|
||||
/// </summary>
|
||||
public class HttpMessageHandlerMoq
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpMessageHandlerMoq"/> class.
|
||||
/// </summary>
|
||||
public HttpMessageHandlerMoq()
|
||||
{
|
||||
Response = new() { StatusCode = HttpStatusCode.OK };
|
||||
Callbacks = new();
|
||||
|
||||
Mock = new();
|
||||
Mock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||
.Callback<HttpRequestMessage, CancellationToken>(async (req, _) =>
|
||||
{
|
||||
var callback = new HttpMessageRequestCallback
|
||||
{
|
||||
Headers = req.Headers,
|
||||
Method = req.Method,
|
||||
Properties = req.Properties,
|
||||
RequestUri = req.RequestUri,
|
||||
Version = req.Version
|
||||
};
|
||||
|
||||
if (req.Content != null)
|
||||
{
|
||||
callback.ContentBytes = await req.Content.ReadAsByteArrayAsync();
|
||||
callback.ContentString = await req.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
Callbacks.Add(callback);
|
||||
})
|
||||
.ReturnsAsync(Response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mocked <see cref="HttpMessageHandler"/>.
|
||||
/// </summary>
|
||||
public Mock<HttpMessageHandler> Mock { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the placed request.
|
||||
/// </summary>
|
||||
public List<HttpMessageRequestCallback> Callbacks { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP response, that should be "sent".
|
||||
/// </summary>
|
||||
public HttpResponseMessage Response { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disposes and resets the <see cref="Response"/> and <see cref="Callbacks"/>.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Response.Dispose();
|
||||
Response = new() { StatusCode = HttpStatusCode.OK };
|
||||
|
||||
Callbacks.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the number of calls to the HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="times"></param>
|
||||
public void Verify(Times times)
|
||||
=> Mock.Protected().Verify("SendAsync", times, ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
|
||||
|
||||
/// <summary>
|
||||
/// Represents the placed HTTP request.
|
||||
/// </summary>
|
||||
public class HttpMessageRequestCallback
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the contents of the HTTP message.
|
||||
/// </summary>
|
||||
public byte[] ContentBytes { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the contents of the HTTP message.
|
||||
/// </summary>
|
||||
public string ContentString { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of HTTP request headers.
|
||||
/// </summary>
|
||||
public HttpRequestHeaders Headers { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP method used by the HTTP request message.
|
||||
/// </summary>
|
||||
public HttpMethod Method { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets of properties for the HTTP request.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Properties { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Uri"/> used for the HTTP request.
|
||||
/// </summary>
|
||||
public Uri RequestUri { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="RequestUri"/> string representation.
|
||||
/// </summary>
|
||||
public string RequestUrl => RequestUri?.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP message version.
|
||||
/// </summary>
|
||||
public Version Version { get; internal set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using DNS.Client;
|
||||
using DNS.Protocol;
|
||||
|
||||
@@ -170,18 +171,17 @@ namespace System
|
||||
var mailAddress = new MailAddress(email);
|
||||
bool isValid = mailAddress.Address == email;
|
||||
|
||||
if (isValid && nameservers != null)
|
||||
if (isValid && nameservers?.Any() == true)
|
||||
{
|
||||
bool exists = false;
|
||||
foreach (var nameserver in nameservers)
|
||||
{
|
||||
var clientRequest = new ClientRequest(nameserver) { RecursionDesired = true };
|
||||
clientRequest.Questions.Add(new Question(Domain.FromString(mailAddress.Host), RecordType.MX));
|
||||
var client = new DnsClient(nameserver);
|
||||
var waitTask = Task.Run(async () => await client.Resolve(mailAddress.Host, RecordType.MX));
|
||||
waitTask.Wait();
|
||||
|
||||
var response = clientRequest.Resolve()
|
||||
.ConfigureAwait(false)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var response = waitTask.Result;
|
||||
waitTask.Dispose();
|
||||
|
||||
if (response.ResponseCode != ResponseCode.NoError)
|
||||
continue;
|
||||
|
||||
@@ -6,10 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.3.0...master) - 0000-00-00
|
||||
### Added
|
||||
|
||||
- New NuGet package `AMWD.Common.Moq` with `HttpRequestHandlerMoq` class
|
||||
- Supporting `InMemory` Database as provider
|
||||
|
||||
### Changed
|
||||
- Enhanced Stopwatch/Timer delta due to unsharp resolution using timers
|
||||
- `IBasicAuthenticationValidator` now requires also the realm (resolving a string on DI is bad style)
|
||||
|
||||
|
||||
## [v1.3.0](https://git.am-wd.de/AM.WD/common/compare/v1.2.0...v1.3.0) - 2021-12-21
|
||||
|
||||
@@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F2C7556A-99E
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E5DF156A-6C8B-4004-BA4C-A8DDE6FD3ECD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AMWD.Common.Moq", "AMWD.Common.Moq\AMWD.Common.Moq.csproj", "{6EBA2792-0B66-4C90-89A1-4E1D26D16443}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -48,6 +50,10 @@ Global
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6EBA2792-0B66-4C90-89A1-4E1D26D16443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6EBA2792-0B66-4C90-89A1-4E1D26D16443}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6EBA2792-0B66-4C90-89A1-4E1D26D16443}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6EBA2792-0B66-4C90-89A1-4E1D26D16443}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -57,6 +63,7 @@ Global
|
||||
{725F40C9-8172-487F-B3D0-D7E38B4DB197} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
{7091CECF-C981-4FB9-9CC6-91C4E65A6356} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F} = {E5DF156A-6C8B-4004-BA4C-A8DDE6FD3ECD}
|
||||
{6EBA2792-0B66-4C90-89A1-4E1D26D16443} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {961E8DF8-DDF5-4D10-A510-CE409E9962AC}
|
||||
|
||||
11
build.cmd
11
build.cmd
@@ -40,3 +40,14 @@ rmdir /S /Q bin
|
||||
dotnet build -c %Configuration% --nologo --no-incremental
|
||||
move bin\%Configuration%\*.nupkg ..\artifacts
|
||||
move bin\%Configuration%\*.snupkg ..\artifacts
|
||||
|
||||
|
||||
|
||||
cd "%~dp0"
|
||||
cd "AMWD.Common.Moq"
|
||||
powershell write-host -fore Blue Building AMWD.Common.Moq
|
||||
|
||||
rmdir /S /Q bin
|
||||
dotnet build -c %Configuration% --nologo --no-incremental
|
||||
move bin\%Configuration%\*.nupkg ..\artifacts
|
||||
move bin\%Configuration%\*.snupkg ..\artifacts
|
||||
7
build.sh
7
build.sh
@@ -28,3 +28,10 @@ dotnet build -c ${CONFIGURATION} --nologo --no-incremental
|
||||
mv bin/${CONFIGURATION}/*.nupkg ../artifacts
|
||||
mv bin/${CONFIGURATION}/*.snupkg ../artifacts
|
||||
popd
|
||||
|
||||
pushd AMWD.Common.Moq
|
||||
rm -rf bin
|
||||
dotnet build -c ${CONFIGURATION} --nologo --no-incremental
|
||||
mv bin/${CONFIGURATION}/*.nupkg ../artifacts
|
||||
mv bin/${CONFIGURATION}/*.snupkg ../artifacts
|
||||
popd
|
||||
|
||||
Reference in New Issue
Block a user