Skip to content

Commit

Permalink
Merge pull request #14015 from abpframework/dapr-improvements
Browse files Browse the repository at this point in the history
Dapr improvements & documentation
  • Loading branch information
hikalkan authored Sep 15, 2022
2 parents cd0bb3c + ea17fbf commit c1e6883
Show file tree
Hide file tree
Showing 17 changed files with 752 additions and 46 deletions.
469 changes: 469 additions & 0 deletions docs/en/Dapr/Index.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/en/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,10 @@
}
]
},
{
"text": "Dapr Integration",
"path": "Dapr/Index.md"
},
{
"text": "Testing",
"path": "Testing.md"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public virtual async Task<List<AbpAspNetCoreMvcDaprSubscriptionDefinition>> Subs
[HttpPost(AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl)]
public virtual async Task<IActionResult> EventsAsync()
{
this.HttpContext.ValidateDaprAppApiToken();

var bodyJsonDocument = await JsonDocument.ParseAsync(HttpContext.Request.Body);
var request = JsonSerializer.Deserialize<AbpAspNetCoreMvcDaprSubscriptionRequest>(bodyJsonDocument.RootElement.GetRawText(),
HttpContext.RequestServices.GetRequiredService<IOptions<JsonOptions>>().Value.JsonSerializerOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson;

public class AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter : JsonConverter<AbpAspNetCoreMvcDaprSubscriptionDefinition>
{
private JsonSerializerOptions _writeJsonSerializerOptions;
private JsonSerializerOptions? _writeJsonSerializerOptions;

public override AbpAspNetCoreMvcDaprSubscriptionDefinition Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization;
using Volo.Abp.Dapr;
using Volo.Abp.DependencyInjection;

namespace Volo.Abp.AspNetCore.Mvc.Dapr;

public class DaprAppApiTokenValidator : IDaprAppApiTokenValidator, ISingletonDependency
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected HttpContext HttpContext => GetHttpContext();

public DaprAppApiTokenValidator(IHttpContextAccessor httpContextAccessor)
{
HttpContextAccessor = httpContextAccessor;
}

public virtual void CheckDaprAppApiToken()
{
var expectedAppApiToken = GetConfiguredAppApiTokenOrNull();
if (expectedAppApiToken.IsNullOrWhiteSpace())
{
return;
}

var headerAppApiToken = GetDaprAppApiTokenOrNull();
if (headerAppApiToken.IsNullOrWhiteSpace())
{
throw new AbpAuthorizationException("Expected Dapr App API Token is not provided! Dapr should set the 'dapr-api-token' HTTP header.");
}

if (expectedAppApiToken != headerAppApiToken)
{
throw new AbpAuthorizationException("The Dapr App API Token (provided in the 'dapr-api-token' HTTP header) doesn't match the expected value!");
}
}

public virtual bool IsValidDaprAppApiToken()
{
var expectedAppApiToken = GetConfiguredAppApiTokenOrNull();
if (expectedAppApiToken.IsNullOrWhiteSpace())
{
return true;
}

var headerAppApiToken = GetDaprAppApiTokenOrNull();
return expectedAppApiToken == headerAppApiToken;
}

public virtual string? GetDaprAppApiTokenOrNull()
{
string apiTokenHeader = HttpContext.Request.Headers["dapr-api-token"];
if (string.IsNullOrEmpty(apiTokenHeader) || apiTokenHeader.Length < 1)
{
return null;
}

return apiTokenHeader;
}

protected virtual string? GetConfiguredAppApiTokenOrNull()
{
return HttpContext
.RequestServices
.GetRequiredService<IDaprApiTokenProvider>()
.GetAppApiToken();
}

protected virtual HttpContext GetHttpContext()
{
return HttpContextAccessor.HttpContext ?? throw new AbpException("HttpContext is not available!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace Volo.Abp.AspNetCore.Mvc.Dapr;

public static class DaprHttpContextExtensions
{
public static void ValidateDaprAppApiToken(this HttpContext httpContext)
{
httpContext
.RequestServices
.GetRequiredService<IDaprAppApiTokenValidator>()
.CheckDaprAppApiToken();
}

public static bool IsValidDaprAppApiToken(this HttpContext httpContext)
{
return httpContext
.RequestServices
.GetRequiredService<IDaprAppApiTokenValidator>()
.IsValidDaprAppApiToken();
}

public static string? GetDaprAppApiTokenOrNull(HttpContext httpContext)
{
return httpContext
.RequestServices
.GetRequiredService<IDaprAppApiTokenValidator>()
.GetDaprAppApiTokenOrNull();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Volo.Abp.AspNetCore.Mvc.Dapr;

public interface IDaprAppApiTokenValidator
{
void CheckDaprAppApiToken();
bool IsValidDaprAppApiToken();
string? GetDaprAppApiTokenOrNull();
}
63 changes: 44 additions & 19 deletions framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs
Original file line number Diff line number Diff line change
@@ -1,48 +1,73 @@
using System.Collections.Concurrent;
using System.Text.Json;
using System.Text.Json;
using Dapr.Client;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json.SystemTextJson;

namespace Volo.Abp.Dapr;

public class AbpDaprClientFactory : ITransientDependency
public class AbpDaprClientFactory : IAbpDaprClientFactory, ISingletonDependency
{
protected AbpDaprOptions Options { get; }
protected AbpSystemTextJsonSerializerOptions SystemTextJsonSerializerOptions { get; }
protected AbpDaprOptions DaprOptions { get; }
protected JsonSerializerOptions JsonSerializerOptions { get; }
protected IDaprApiTokenProvider DaprApiTokenProvider { get; }

public AbpDaprClientFactory(
IOptions<AbpDaprOptions> options,
IOptions<AbpSystemTextJsonSerializerOptions> systemTextJsonSerializerOptions)
IOptions<AbpSystemTextJsonSerializerOptions> systemTextJsonSerializerOptions,
IDaprApiTokenProvider daprApiTokenProvider)
{
Options = options.Value;
SystemTextJsonSerializerOptions = systemTextJsonSerializerOptions.Value;
DaprApiTokenProvider = daprApiTokenProvider;
DaprOptions = options.Value;
JsonSerializerOptions = CreateJsonSerializerOptions(systemTextJsonSerializerOptions.Value);
}

public virtual async Task<DaprClient> CreateAsync()
public virtual DaprClient Create(Action<DaprClientBuilder>? builderAction = null)
{
var builder = new DaprClientBuilder()
.UseJsonSerializationOptions(await CreateJsonSerializerOptions());
.UseJsonSerializationOptions(JsonSerializerOptions);

if (!Options.HttpEndpoint.IsNullOrWhiteSpace())
if (!DaprOptions.HttpEndpoint.IsNullOrWhiteSpace())
{
builder.UseHttpEndpoint(Options.HttpEndpoint);
builder.UseHttpEndpoint(DaprOptions.HttpEndpoint);
}

if (!Options.GrpcEndpoint.IsNullOrWhiteSpace())
if (!DaprOptions.GrpcEndpoint.IsNullOrWhiteSpace())
{
builder.UseGrpcEndpoint(Options.GrpcEndpoint);
builder.UseGrpcEndpoint(DaprOptions.GrpcEndpoint);
}

var apiToken = DaprApiTokenProvider.GetDaprApiToken();
if (!apiToken.IsNullOrWhiteSpace())
{
builder.UseDaprApiToken(apiToken);
}

builderAction?.Invoke(builder);

return builder.Build();
}

private readonly static ConcurrentDictionary<string, JsonSerializerOptions> JsonSerializerOptionsCache = new ConcurrentDictionary<string, JsonSerializerOptions>();
public virtual HttpClient CreateHttpClient(
string? appId = null,
string? daprEndpoint = null,
string? daprApiToken = null)
{
if(daprEndpoint.IsNullOrWhiteSpace() &&
!DaprOptions.HttpEndpoint.IsNullOrWhiteSpace())
{
daprEndpoint = DaprOptions.HttpEndpoint;
}

protected virtual Task<JsonSerializerOptions> CreateJsonSerializerOptions()
return DaprClient.CreateInvokeHttpClient(
appId,
daprEndpoint,
daprApiToken ?? DaprApiTokenProvider.GetDaprApiToken()
);
}

protected virtual JsonSerializerOptions CreateJsonSerializerOptions(AbpSystemTextJsonSerializerOptions systemTextJsonSerializerOptions)
{
return Task.FromResult(JsonSerializerOptionsCache.GetOrAdd(nameof(AbpDaprClientFactory),
_ => new JsonSerializerOptions(SystemTextJsonSerializerOptions.JsonSerializerOptions)));
return new JsonSerializerOptions(systemTextJsonSerializerOptions.JsonSerializerOptions);
}
}
}
52 changes: 51 additions & 1 deletion framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Json;
using Volo.Abp.Modularity;

Expand All @@ -10,6 +12,54 @@ public class AbpDaprModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();

ConfigureDaprOptions(configuration);

context.Services.TryAddSingleton(
serviceProvider => serviceProvider
.GetRequiredService<IAbpDaprClientFactory>()
.Create()
);
}

private void ConfigureDaprOptions(IConfiguration configuration)
{
Configure<AbpDaprOptions>(configuration.GetSection("Dapr"));
Configure<AbpDaprOptions>(options =>
{
if (options.DaprApiToken.IsNullOrWhiteSpace())
{
var confEnv = configuration["DAPR_API_TOKEN"];
if (!confEnv.IsNullOrWhiteSpace())
{
options.DaprApiToken = confEnv;
}
else
{
var env = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
if (!env.IsNullOrWhiteSpace())
{
options.DaprApiToken = env;
}
}
}

if (options.AppApiToken.IsNullOrWhiteSpace())
{
var confEnv = configuration["APP_API_TOKEN"];
if (!confEnv.IsNullOrWhiteSpace())
{
options.AppApiToken = confEnv;
}
else
{
var env = Environment.GetEnvironmentVariable("APP_API_TOKEN");
if (!env.IsNullOrWhiteSpace())
{
options.AppApiToken = env;
}
}
}
});
}
}
8 changes: 5 additions & 3 deletions framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

public class AbpDaprOptions
{
public string AppId { get; set; }

public string HttpEndpoint { get; set; }

public string GrpcEndpoint { get; set; }
}

public string DaprApiToken { get; set; }

public string AppApiToken { get; set; }
}
24 changes: 24 additions & 0 deletions framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/DaprApiTokenProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;

namespace Volo.Abp.Dapr;

public class DaprApiTokenProvider : IDaprApiTokenProvider, ISingletonDependency
{
protected AbpDaprOptions Options { get; }

public DaprApiTokenProvider(IOptions<AbpDaprOptions> options)
{
Options = options.Value;
}

public virtual string? GetDaprApiToken()
{
return Options.DaprApiToken;
}

public virtual string? GetAppApiToken()
{
return Options.AppApiToken;
}
}
14 changes: 14 additions & 0 deletions framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IAbpDaprClientFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Dapr.Client;

namespace Volo.Abp.Dapr;

public interface IAbpDaprClientFactory
{
DaprClient Create(Action<DaprClientBuilder>? builderAction = null);

HttpClient CreateHttpClient(
string? appId = null,
string? daprEndpoint = null,
string? daprApiToken = null
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Volo.Abp.Dapr;

public interface IDaprApiTokenProvider
{
string? GetDaprApiToken();

string? GetAppApiToken();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface IAbpDistributedLock
/// Returns null if the lock could not be handled.
/// </summary>
/// <param name="name">The name of the lock</param>
/// <param name="timeout">Timeout value</param>
/// <param name="timeout">How long to wait before giving up on the acquisition attempt. Defaults to 0</param>
/// <param name="cancellationToken">Cancellation token</param>
[ItemCanBeNull]
Task<IAbpDistributedLockHandle> TryAcquireAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ public class AbpDistributedLockDaprOptions
{
public string StoreName { get; set; }

public TimeSpan DefaultTimeout { get; set; }
public string? Owner { get; set; }

public TimeSpan DefaultExpirationTimeout { get; set; }

public AbpDistributedLockDaprOptions()
{
DefaultTimeout = TimeSpan.FromSeconds(30);
DefaultExpirationTimeout = TimeSpan.FromMinutes(2);
}
}
Loading

0 comments on commit c1e6883

Please sign in to comment.