* Add support for secret accessor functions in JavaScript Refactored the rendering and evaluation of JavaScript to include method definitions alongside existing properties. Enhanced secret handling by generating asynchronous accessor functions, improving the clarity and functionality of secret management in scripting. * Refactor secret retrieval logic in JavaScript engine configuration Refactored the code to use a dedicated method `ResolveSecretAsync` for secret retrieval, improving clarity and maintainability. Added a check to ensure that only active secrets are decrypted, enhancing robustness and error handling. * Add SecretExpired notification and mediator to updater Introduces a new SecretExpired notification class and integrates it within DefaultExpiredSecretsUpdater. The updater now sends a SecretExpired notification via the mediator upon expiring a secret.
41 lines
1.5 KiB
C#
41 lines
1.5 KiB
C#
using System.Dynamic;
|
|
using Elsa.JavaScript.Notifications;
|
|
using Elsa.Mediator.Contracts;
|
|
using Elsa.Secrets.Management;
|
|
using Humanizer;
|
|
using JetBrains.Annotations;
|
|
|
|
namespace Elsa.Secrets.Scripting.JavaScript;
|
|
|
|
/// A handler that configures the Jint engine with secrets.
|
|
[UsedImplicitly]
|
|
public class ConfigureEngineWithSecrets(ISecretManager secretManager, IDecryptor decryptor) : INotificationHandler<EvaluatingJavaScript>
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken)
|
|
{
|
|
await GenerateSecretAccessorFunctions(notification, cancellationToken);
|
|
}
|
|
|
|
private async Task GenerateSecretAccessorFunctions(EvaluatingJavaScript notification, CancellationToken cancellationToken)
|
|
{
|
|
var engine = notification.Engine;
|
|
var secrets = (await secretManager.ListAsync(cancellationToken)).ToList();
|
|
|
|
IDictionary<string, object?> secretsContainer = new ExpandoObject();
|
|
|
|
foreach (var secret in secrets)
|
|
{
|
|
secretsContainer[$"get{secret.Name.Pascalize()}Async"] = () => ResolveSecretAsync(secret, cancellationToken);
|
|
}
|
|
|
|
engine.SetValue("secrets", secretsContainer);
|
|
}
|
|
|
|
private async Task<string> ResolveSecretAsync(Secret secret, CancellationToken cancellationToken)
|
|
{
|
|
if (secret.Status != SecretStatus.Active)
|
|
throw new InvalidOperationException($"Secret '{secret.Name}' is not active.");
|
|
return await decryptor.DecryptAsync(secret.EncryptedValue, cancellationToken);
|
|
}
|
|
} |