Merge pull request #6673 from elsa-workflows/task/move-sastokens-to-core

Add back SasToken project.
This commit is contained in:
Matt 2025-05-23 15:16:57 +01:00 committed by GitHub
commit a0b1b299c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 181 additions and 2 deletions

View file

@ -31,7 +31,6 @@
<PackageVersion Include="Elsa.Persistence.Elasticsearch" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.Persistence.MongoDb" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.Retention" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.SasTokens" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.ServiceBus.Kafka" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.ServiceBus.MassTransit" Version="3.6.0-preview.29" />
<PackageVersion Include="Elsa.ServiceBus.MassTransit.AzureServiceBus" Version="3.6.0-preview.29" />

View file

@ -260,6 +260,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.Liquid", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.Python", "src\modules\Elsa.Expressions.Python\Elsa.Expressions.Python.csproj", "{9D8FB664-88B4-10BE-58A2-D9A1644AD2E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.SasTokens", "src\modules\Elsa.SasTokens\Elsa.SasTokens.csproj", "{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -444,6 +446,10 @@ Global
{9D8FB664-88B4-10BE-58A2-D9A1644AD2E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D8FB664-88B4-10BE-58A2-D9A1644AD2E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D8FB664-88B4-10BE-58A2-D9A1644AD2E4}.Release|Any CPU.Build.0 = Release|Any CPU
{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -520,6 +526,7 @@ Global
{08B69CC4-B5F0-44E8-FA7A-6BF6F00CA40A} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{6AF53651-99F0-1DE0-D37B-4FF6B0348DBB} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{9D8FB664-88B4-10BE-58A2-D9A1644AD2E4} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{A7DE02E3-405B-B6BA-7E47-9E27D4BEFB24} = {5948B0A5-7873-4DBB-BA03-EB283D6EA91B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E}

View file

@ -9,7 +9,6 @@
<ItemGroup>
<PackageReference Include="FluentStorage" />
<PackageReference Include="Elsa.SasTokens" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.Resilience" />
<PackageReference Include="Polly" />
@ -22,6 +21,7 @@
<ProjectReference Include="..\Elsa.Expressions.JavaScript\Elsa.Expressions.JavaScript.csproj" />
<ProjectReference Include="..\Elsa.Expressions.Liquid\Elsa.Expressions.Liquid.csproj" />
<ProjectReference Include="..\Elsa.Resilience\Elsa.Resilience.csproj" />
<ProjectReference Include="..\Elsa.SasTokens\Elsa.SasTokens.csproj" />
<ProjectReference Include="..\Elsa.Workflows.Runtime\Elsa.Workflows.Runtime.csproj" />
</ItemGroup>

View file

@ -0,0 +1,66 @@
using System.Text.Json;
using Microsoft.AspNetCore.DataProtection;
namespace Elsa.SasTokens.Contracts;
/// <summary>
/// A service that can create and decrypt SAS (Shared Access Signature) tokens using the <see cref="Microsoft.AspNetCore.DataProtection.IDataProtector"/> service.
/// </summary>
public class DataProtectorTokenService : ITokenService
{
private readonly IDataProtector _dataProtector;
/// <summary>
/// Initializes a new instance of the <see cref="DataProtectorTokenService"/> class.
/// </summary>
public DataProtectorTokenService(IDataProtectionProvider dataProtector)
{
_dataProtector = dataProtector.CreateProtector("Elsa Tokens");
}
/// <inheritdoc />
public string CreateToken<T>(T payload, TimeSpan lifetime)
{
var json = JsonSerializer.Serialize(payload);
return _dataProtector.ToTimeLimitedDataProtector().Protect(json, lifetime);
}
/// <inheritdoc />
public string CreateToken<T>(T payload, DateTimeOffset expiresAt)
{
var json = JsonSerializer.Serialize(payload);
return _dataProtector.ToTimeLimitedDataProtector().Protect(json, expiresAt);
}
/// <inheritdoc />
public string CreateToken<T>(T payload)
{
var json = JsonSerializer.Serialize(payload);
return _dataProtector.Protect(json);
}
/// <inheritdoc />
public bool TryDecryptToken<T>(string token, out T payload)
{
payload = default!;
try
{
payload = DecryptToken<T>(token);
return true;
}
catch
{
// ignored.
}
return false;
}
/// <inheritdoc />
public T DecryptToken<T>(string token)
{
var json = _dataProtector.Unprotect(token);
return JsonSerializer.Deserialize<T>(json)!;
}
}

View file

@ -0,0 +1,32 @@
namespace Elsa.SasTokens.Contracts;
/// <summary>
/// A service that can create and decrypt SAS (Shared Access Signature) tokens.
/// </summary>
public interface ITokenService
{
/// <summary>
/// Creates a SAS (Shared Access Signature) token containing the specified data.
/// </summary>
string CreateToken<T>(T payload, TimeSpan lifetime);
/// <summary>
/// Creates a SAS (Shared Access Signature) token containing the specified data.
/// </summary>
string CreateToken<T>(T payload, DateTimeOffset expiresAt);
/// <summary>
/// Creates a SAS (Shared Access Signature) token containing the specified data.
/// </summary>
string CreateToken<T>(T payload);
/// <summary>
/// Decrypts the specified SAS token.
/// </summary>
T DecryptToken<T>(string token);
/// <summary>
/// Decrypts the specified SAS token.
/// </summary>
bool TryDecryptToken<T>(string token, out T payload);
}

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>
Provides services to generate SAS tokens.
</Description>
<PackageTags>elsa module security sas tokens</PackageTags>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\Elsa.Features\Elsa.Features.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,20 @@
using Elsa.Features.Services;
using Elsa.SasTokens.Features;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
/// <summary>
/// Provides extensions to install the <see cref="SasTokens"/> feature.
/// </summary>
public static class ModuleExtensions
{
/// <summary>
/// Install the <see cref="SasTokens"/> feature.
/// </summary>
public static IModule UseSasTokens(this IModule module, Action<SasTokensFeature>? configure = default)
{
module.Configure(configure);
return module;
}
}

View file

@ -0,0 +1,35 @@
using Elsa.Features.Abstractions;
using Elsa.Features.Services;
using Elsa.SasTokens.Contracts;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.SasTokens.Features;
/// <summary>
/// Adds the SAS tokens feature to the workflow runtime.
/// </summary>
/// <inheritdoc />
public class SasTokensFeature(IModule module) : FeatureBase(module)
{
/// <summary>
/// Configures the <see cref="IDataProtectionBuilder"/> used for setting up data protection.
/// Defaults to setting the application name to "Elsa Workflows".
/// </summary>
public Action<IDataProtectionBuilder> ConfigureDataProtectionBuilder { get; set; } = b => { b.SetApplicationName("Elsa Workflows"); };
/// <summary>
/// Factory method to create an instance of <see cref="ITokenService"/>.
/// Defaults to creating a <see cref="DataProtectorTokenService"/> using dependency injection.
/// </summary>
public Func<IServiceProvider, ITokenService> TokenService { get; set; } = sp => ActivatorUtilities.CreateInstance<DataProtectorTokenService>(sp);
/// <inheritdoc />
public override void Apply()
{
var builder = Services.AddDataProtection();
ConfigureDataProtectionBuilder(builder);
Services.AddScoped(TokenService);
}
}

View file

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