Merge pull request #6438 from elsa-workflows/task/remove-orchard-core
Remove Elsa.OrchardCore module.
This commit is contained in:
commit
a8e5a97f93
7
Elsa.sln
7
Elsa.sln
|
|
@ -302,8 +302,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "trace-lens", "trace-lens",
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integrations", "integrations", "{EBD0CF78-C5D7-4B4B-94C9-C5D8C20B6F59}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.OrchardCore", "src\modules\Elsa.OrchardCore\Elsa.OrchardCore.csproj", "{B0460856-7E6D-4B1E-B243-8E20662FC32E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "agents", "agents", "{50470834-4CD8-479A-8B58-0A1869BA5D37}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Agents.Core", "src\modules\Elsa.Agents.Core\Elsa.Agents.Core.csproj", "{5BD671F0-9603-4C2F-8364-54B02986EAA2}"
|
||||
|
|
@ -755,10 +753,6 @@ Global
|
|||
{47FBCB04-0C2D-453C-BE2F-7052CAC22524}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47FBCB04-0C2D-453C-BE2F-7052CAC22524}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47FBCB04-0C2D-453C-BE2F-7052CAC22524}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B0460856-7E6D-4B1E-B243-8E20662FC32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0460856-7E6D-4B1E-B243-8E20662FC32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0460856-7E6D-4B1E-B243-8E20662FC32E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0460856-7E6D-4B1E-B243-8E20662FC32E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5BD671F0-9603-4C2F-8364-54B02986EAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5BD671F0-9603-4C2F-8364-54B02986EAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5BD671F0-9603-4C2F-8364-54B02986EAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -1005,7 +999,6 @@ Global
|
|||
{6DDB9ECF-D454-4894-A262-A6BB3026E61E} = {B32DB9B2-AD6C-48A5-8682-4373CB045185}
|
||||
{16B570BC-E293-4A19-B20E-5C97BAF8476B} = {B32DB9B2-AD6C-48A5-8682-4373CB045185}
|
||||
{EBD0CF78-C5D7-4B4B-94C9-C5D8C20B6F59} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{B0460856-7E6D-4B1E-B243-8E20662FC32E} = {EBD0CF78-C5D7-4B4B-94C9-C5D8C20B6F59}
|
||||
{50470834-4CD8-479A-8B58-0A1869BA5D37} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{5BD671F0-9603-4C2F-8364-54B02986EAA2} = {50470834-4CD8-479A-8B58-0A1869BA5D37}
|
||||
{154525CD-3726-45B7-9A9C-553BBC60EB10} = {50470834-4CD8-479A-8B58-0A1869BA5D37}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Mediator.Contracts;
|
||||
using Elsa.OrchardCore.Stimuli;
|
||||
using Elsa.OrchardCore.WebhookPayloads;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
public class ContentItemEvent : Trigger<ContentItemEventPayload>, INotification
|
||||
{
|
||||
/// <summary>
|
||||
/// The content type to handle the event for.
|
||||
/// </summary>
|
||||
[Input(Description = "The content type to handle the event for.")]
|
||||
public string ContentType { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The event to handle.
|
||||
/// </summary>
|
||||
[Input(Description = "The event to handle the event for.")]
|
||||
public string EventType { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
if (!context.IsTriggerOfWorkflow())
|
||||
{
|
||||
context.CreateBookmark(GetStimulus(context.ExpressionExecutionContext), OnResumeAsync);
|
||||
return;
|
||||
}
|
||||
|
||||
await ExecuteInternalAsync(context);
|
||||
}
|
||||
|
||||
protected override object GetTriggerPayload(TriggerIndexingContext context) => new ContentItemEventStimulus(ContentType, EventType);
|
||||
private async ValueTask OnResumeAsync(ActivityExecutionContext context) => await ExecuteInternalAsync(context);
|
||||
private object GetStimulus(ExpressionExecutionContext context) => new ContentItemEventStimulus(ContentType, EventType);
|
||||
|
||||
private async Task ExecuteInternalAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var payload = context.GetWorkflowInput<ContentItemEventPayload>();
|
||||
context.SetResult(payload);
|
||||
await context.CompleteActivityAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Expressions.Helpers;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Patches a content item", Kind = ActivityKind.Task)]
|
||||
public class CreateContentItem : CodeActivity<JsonObject>
|
||||
{
|
||||
[Input(Description = "The content type of the content item to create.")]
|
||||
public Input<string> ContentType { get; set; } = default!;
|
||||
|
||||
[Input(Description = "The properties to apply to the content item.")]
|
||||
public Input<object> Properties { get; set; } = default!;
|
||||
|
||||
[Input(Description = "Whether to publish the content item.")]
|
||||
public Input<bool> Publish { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var contentType = ContentType.Get(context);
|
||||
var publish = Publish.Get(context);
|
||||
var properties = Properties.Get(context).ConvertTo<JsonObject>()!;
|
||||
var apiClient = context.GetRequiredService<IRestApiClient>();
|
||||
var request = new CreateContentItemRequest
|
||||
{
|
||||
ContentType = contentType,
|
||||
Properties = properties,
|
||||
Publish = publish
|
||||
};
|
||||
var contentItem = await apiClient.CreateContentItemAsync(request, context.CancellationToken);
|
||||
context.SetResult(contentItem);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Localizes a content item", Kind = ActivityKind.Task)]
|
||||
public class LocalizeContentItem : CodeActivity<JsonObject>
|
||||
{
|
||||
[Input(Description = "The ID of the content item to localize.")]
|
||||
public Input<string> ContentItemId { get; set; } = default!;
|
||||
|
||||
[Input(Description = "The culture code to use when creating a localized version.")]
|
||||
public Input<string> CultureCode { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var contentItemId = ContentItemId.Get(context);
|
||||
var cultureCode = CultureCode.Get(context);
|
||||
var apiClient = context.GetRequiredService<IRestApiClient>();
|
||||
var request = new LocalizeContentItemRequest
|
||||
{
|
||||
CultureCode = cultureCode
|
||||
};
|
||||
var localizedContentItem = await apiClient.LocalizeContentItemAsync(contentItemId, request, context.CancellationToken);
|
||||
context.SetResult(localizedContentItem);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Patches a content item", Kind = ActivityKind.Task)]
|
||||
public class PatchContentItem : CodeActivity<JsonObject>
|
||||
{
|
||||
[Input(Description = "The ID of the content item to patch.")]
|
||||
public Input<string> ContentItemId { get; set; } = default!;
|
||||
|
||||
[Input(Description = "The patch to apply to the content item.")]
|
||||
public Input<JsonObject> Patch { get; set; } = default!;
|
||||
|
||||
[Input(Description = "Whether to publish the patched content item.")]
|
||||
public Input<bool> Publish { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var contentItemId = ContentItemId.Get(context);
|
||||
var publish = Publish.Get(context);
|
||||
var patch = Patch.Get(context);
|
||||
var apiClient = context.GetRequiredService<IRestApiClient>();
|
||||
var request = new PatchContentItemRequest
|
||||
{
|
||||
Patch = patch,
|
||||
Publish = publish
|
||||
};
|
||||
var patchedContentItem = await apiClient.PatchContentItemAsync(contentItemId, request, context.CancellationToken);
|
||||
context.SetResult(patchedContentItem);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Returns tag content items for the specified set of tags. If a tag doesn't exist, it is created.", Kind = ActivityKind.Task)]
|
||||
public class ResolveTags : CodeActivity<JsonObject>
|
||||
{
|
||||
[Input(Description = "The tags to resolve.")]
|
||||
public Input<ICollection<string>> Tags { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var tags = Tags.Get(context);
|
||||
var apiClient = context.GetRequiredService<IRestApiClient>();
|
||||
var request = new ResolveTagsRequest
|
||||
{
|
||||
Tags = tags
|
||||
};
|
||||
var result = await apiClient.ResolveTagsAsync(request, context.CancellationToken);
|
||||
context.SetResult(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Send a GraphQL query to Orchard Core", DisplayName = "GraphQL Query", Kind = ActivityKind.Task)]
|
||||
public class SendGraphQLQuery : CodeActivity<object>
|
||||
{
|
||||
/// <summary>
|
||||
/// The content type to handle the event for.
|
||||
/// </summary>
|
||||
[Input(Description = "The GraphQL query string to send.")]
|
||||
public Input<string> Query { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var query = Query.Get(context);
|
||||
var client = context.GetRequiredService<IGraphQLClient>();
|
||||
var targetType = Result.GetTargetType(context);
|
||||
var output = await client.SendQueryAsync(query, targetType, context.CancellationToken);
|
||||
context.SetResult(output);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http;
|
||||
using Elsa.OrchardCore.Client;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.OrchardCore.Activities;
|
||||
|
||||
[Activity("OrchardCore", "Orchard Core", "Patches a content item", Kind = ActivityKind.Task)]
|
||||
public class UploadMedia : CodeActivity<JsonObject>
|
||||
{
|
||||
[Input(Description = "The files to upload into the Media Library.")]
|
||||
public Input<ICollection<HttpFile>> Files { get; set; } = default!;
|
||||
|
||||
[Input(Description = "The path to the media library folder to upload.")]
|
||||
public Input<string?> FolderPath { get; set; } = default!;
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var files = Files.Get(context);
|
||||
var folderPath = FolderPath.GetOrDefault(context);
|
||||
var apiClient = context.GetRequiredService<IRestApiClient>();
|
||||
var response = await apiClient.UploadFilesAsync(files, folderPath, context.CancellationToken);
|
||||
context.SetResult(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
using Elsa.OrchardCore.Activities;
|
||||
using Elsa.OrchardCore.Models;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Models;
|
||||
using Humanizer;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Elsa.OrchardCore.ActivityProviders;
|
||||
|
||||
/// <summary>
|
||||
/// An activity provider that generates activity types based on Orchard content type events.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class OrchardContentItemsEventActivityProvider(IOptions<OrchardCoreOptions> options, IActivityFactory activityFactory, IActivityDescriber activityDescriber) : IActivityProvider
|
||||
{
|
||||
public async ValueTask<IEnumerable<ActivityDescriptor>> GetDescriptorsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var contentTypes = options.Value.ContentTypes;
|
||||
var matrix =
|
||||
from contentType in contentTypes
|
||||
from eventType in WebhookEventTypes.GetWebhookEventDescriptors()
|
||||
select new
|
||||
{
|
||||
contentType,
|
||||
eventType
|
||||
};
|
||||
var activities = (await Task.WhenAll(matrix.Select(async x => await CreateActivityDescriptorAsync(x.contentType, x.eventType, cancellationToken)))).ToList();
|
||||
return activities;
|
||||
}
|
||||
|
||||
private async Task<ActivityDescriptor> CreateActivityDescriptorAsync(string contentType, WebhookEventDescriptor eventDescriptor, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var eventType = eventDescriptor.EventType;
|
||||
var humanizedEventName = eventType.Humanize();
|
||||
var description = $"Handles {humanizedEventName} events for {contentType} content items";
|
||||
var name = $"{contentType}{eventType}";
|
||||
var displayName = $"{contentType} {eventType}";
|
||||
var fullTypeName = OrchardCoreActivityNameHelper.GetContentItemEventActivityFullTypeName(contentType, eventType);
|
||||
var activityType = typeof(ContentItemEvent);
|
||||
var activityDescriptor = await activityDescriber.DescribeActivityAsync(activityType, cancellationToken);
|
||||
|
||||
activityDescriptor.TypeName = fullTypeName;
|
||||
activityDescriptor.Name = name;
|
||||
activityDescriptor.DisplayName = displayName;
|
||||
activityDescriptor.Category = "Orchard Core";
|
||||
activityDescriptor.Description = description;
|
||||
activityDescriptor.Constructor = context =>
|
||||
{
|
||||
var activity = (ContentItemEvent)activityFactory.Create(activityType, context);
|
||||
activity.Type = fullTypeName;
|
||||
activity.ContentType = contentType;
|
||||
activity.EventType = eventType;
|
||||
return activity;
|
||||
};
|
||||
|
||||
foreach (var inputDescriptor in activityDescriptor.Inputs)
|
||||
inputDescriptor.IsBrowsable = false;
|
||||
|
||||
return activityDescriptor;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public interface IGraphQLClient
|
||||
{
|
||||
Task<object> SendQueryAsync(string query, Type? targetType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Http;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public interface IRestApiClient
|
||||
{
|
||||
Task<JsonObject> GetContentItemAsync(string contentItemId, CancellationToken cancellationToken = default);
|
||||
Task<JsonObject> PatchContentItemAsync(string contentItemId, PatchContentItemRequest request, CancellationToken cancellationToken = default);
|
||||
Task<JsonObject> LocalizeContentItemAsync(string contentItemId, LocalizeContentItemRequest request, CancellationToken cancellationToken = default);
|
||||
Task<JsonObject> CreateContentItemAsync(CreateContentItemRequest request, CancellationToken cancellationToken = default);
|
||||
Task<JsonObject> UploadFilesAsync(IEnumerable<HttpFile> files, string? folderPath = null, CancellationToken cancellationToken = default);
|
||||
Task<JsonObject> ResolveTagsAsync(ResolveTagsRequest request, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public interface ISecurityTokenClient
|
||||
{
|
||||
Task<SecurityToken> GetSecurityTokenAsync(string clientId, string clientSecret, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public interface ISecurityTokenService
|
||||
{
|
||||
Task<SecurityToken> GetTokenAsync(CancellationToken cancellationToken = default);
|
||||
Task<SecurityToken> RefreshTokenAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class AuthenticatingDelegatingHandler(ISecurityTokenService tokenService) : DelegatingHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var token = await tokenService.GetTokenAsync(cancellationToken);
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
|
||||
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
// Token might be expired; refresh it
|
||||
token = await tokenService.RefreshTokenAsync(cancellationToken);
|
||||
|
||||
// Retry the request with the new token
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
|
||||
response = await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Elsa.OrchardCore.Client.Extensions;
|
||||
|
||||
[PublicAPI]
|
||||
public static class OrchardCoreClientServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddOrchardCoreClient(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<ISecurityTokenService, DefaultSecurityTokenService>();
|
||||
services.AddTransient<AuthenticatingDelegatingHandler>();
|
||||
|
||||
services.AddHttpClient<ISecurityTokenClient, DefaultSecurityTokenClient>((sp, httpClient) =>
|
||||
{
|
||||
var options = sp.GetRequiredService<IOptions<OrchardCoreClientOptions>>().Value;
|
||||
httpClient.BaseAddress = options.BaseAddress;
|
||||
});
|
||||
|
||||
services.AddHttpClient<IGraphQLClient, DefaultGraphQlClient>((sp, httpClient) =>
|
||||
{
|
||||
var options = sp.GetRequiredService<IOptions<OrchardCoreClientOptions>>().Value;
|
||||
httpClient.BaseAddress = options.BaseAddress;
|
||||
}).AddHttpMessageHandler<AuthenticatingDelegatingHandler>();
|
||||
|
||||
services.AddHttpClient<IRestApiClient, DefaultRestApiClient>((sp, httpClient) =>
|
||||
{
|
||||
var options = sp.GetRequiredService<IOptions<OrchardCoreClientOptions>>().Value;
|
||||
httpClient.BaseAddress = options.BaseAddress;
|
||||
}).AddHttpMessageHandler<AuthenticatingDelegatingHandler>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class CreateContentItemRequest
|
||||
{
|
||||
public string ContentType { get; set; } = default!;
|
||||
public JsonNode Properties { get; set; } = default!;
|
||||
public bool Publish { get; set; }
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class LocalizeContentItemRequest
|
||||
{
|
||||
public string CultureCode { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class PatchContentItemRequest
|
||||
{
|
||||
public JsonNode Patch { get; set; } = default!;
|
||||
public bool Publish { get; set; }
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class ResolveTagsRequest
|
||||
{
|
||||
public ICollection<string> Tags { get; set; } = [];
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="AccessToken"></param>
|
||||
/// <param name="TokenType"></param>
|
||||
/// <param name="ExpiresIn"></param>
|
||||
public record SecurityToken(string AccessToken, string TokenType, int ExpiresIn);
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
/// <summary>
|
||||
/// Options related to connecting to an Orchard Core tenant.
|
||||
/// </summary>
|
||||
public class OrchardCoreClientOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The base address of the Orchard Core tenant to interact with.
|
||||
/// </summary>
|
||||
public Uri BaseAddress { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The client ID.
|
||||
/// </summary>
|
||||
public string ClientId { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The client secret.
|
||||
/// </summary>
|
||||
public string ClientSecret { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
using System.Text.Json.Nodes;
|
||||
using Elsa.Expressions.Helpers;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class DefaultGraphQlClient(HttpClient httpClient) : IGraphQLClient
|
||||
{
|
||||
public async Task<object> SendQueryAsync(string query, Type? targetType = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = new StringContent(query, System.Text.Encoding.UTF8, "application/graphql");
|
||||
var response = await httpClient.PostAsync("api/graphql", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
|
||||
targetType ??= typeof(JsonObject);
|
||||
return ObjectConverter.ConvertTo(json, targetType);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Elsa.Http;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class DefaultRestApiClient(HttpClient httpClient) : IRestApiClient
|
||||
{
|
||||
public async Task<JsonObject> GetContentItemAsync(string contentItemId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await httpClient.GetAsync($"api/content/{contentItemId}", cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> PatchContentItemAsync(string contentItemId, PatchContentItemRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = JsonContent.Create(request);
|
||||
var response = await httpClient.PatchAsync($"api/content-items/{contentItemId}", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> LocalizeContentItemAsync(string contentItemId, LocalizeContentItemRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = JsonContent.Create(request);
|
||||
var response = await httpClient.PostAsync($"api/content-items/{contentItemId}/localize", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
return JsonSerializer.Deserialize<JsonObject>(json);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> CreateContentItemAsync(CreateContentItemRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = JsonContent.Create(request);
|
||||
var response = await httpClient.PostAsync("api/content-items", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> UploadFilesAsync(IEnumerable<HttpFile> files, string? folderPath = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = new MultipartFormDataContent();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var streamContent = file.GetStreamContent();
|
||||
content.Add(streamContent);
|
||||
}
|
||||
|
||||
var response = await httpClient.PostAsync($"api/media/upload?path={folderPath}", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> ResolveTagsAsync(ResolveTagsRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = JsonContent.Create(request);
|
||||
var response = await httpClient.PostAsync("api/tags/resolve", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class DefaultSecurityTokenClient(HttpClient httpClient) : ISecurityTokenClient
|
||||
{
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||
};
|
||||
|
||||
public async Task<SecurityToken> GetSecurityTokenAsync(string clientId, string clientSecret, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var content = new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
["grant_type"] = "client_credentials",
|
||||
["client_id"] = clientId,
|
||||
["client_secret"] = clientSecret
|
||||
});
|
||||
|
||||
var response = await httpClient.PostAsync("/connect/token", content, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
return JsonSerializer.Deserialize<SecurityToken>(responseContent, _jsonSerializerOptions);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Elsa.OrchardCore.Client;
|
||||
|
||||
public class DefaultSecurityTokenService(IMemoryCache memoryCache, ISecurityTokenClient securityTokenClient, IOptions<OrchardCoreClientOptions> options) : ISecurityTokenService
|
||||
{
|
||||
private readonly string _cacheKey = $"{nameof(DefaultSecurityTokenService)}:{Guid.NewGuid()}";
|
||||
|
||||
public async Task<SecurityToken> GetTokenAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return (await memoryCache.GetOrCreateAsync(_cacheKey, async entry =>
|
||||
{
|
||||
var securityToken = await RequestSecurityTokenAsync(cancellationToken);
|
||||
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(securityToken.ExpiresIn);
|
||||
return securityToken;
|
||||
}))!;
|
||||
}
|
||||
|
||||
public Task<SecurityToken> RefreshTokenAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return RequestSecurityTokenAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private Task<SecurityToken> RequestSecurityTokenAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var clientId = options.Value.ClientId;
|
||||
var clientSecret = options.Value.ClientSecret;
|
||||
return securityTokenClient.GetSecurityTokenAsync(clientId, clientSecret, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>
|
||||
Provides integrations with an Orchard Core application instances through activities and via HTTP.
|
||||
</Description>
|
||||
<PackageTags>elsa module orchardcore</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Elsa.Http\Elsa.Http.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Webhooks\Elsa.Webhooks.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Workflows.Management\Elsa.Workflows.Management.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Workflows.Runtime\Elsa.Workflows.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=client_005Ccontracts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=client_005Cdelegatinghandlers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=client_005Cmodels/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=client_005Coptions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=client_005Cservices/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=constants/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helpers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=options/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
using Elsa.Features.Services;
|
||||
using Elsa.OrchardCore.Features;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Elsa.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Adds extensions to <see cref="IModule"/> that enables the <see cref="OrchardCoreFeature"/> feature.
|
||||
/// </summary>
|
||||
public static class ModuleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables and configures the <see cref="OrchardCoreFeature"/> feature.
|
||||
/// </summary>
|
||||
public static IModule UseOrchardCore(this IModule module, Action<OrchardCoreFeature>? configure = default)
|
||||
{
|
||||
module.Configure(configure);
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Features.Abstractions;
|
||||
using Elsa.Features.Attributes;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.OrchardCore.ActivityProviders;
|
||||
using Elsa.OrchardCore.Client.Extensions;
|
||||
using Elsa.OrchardCore.WebhookPayloads;
|
||||
using Elsa.Webhooks.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.OrchardCore.Features;
|
||||
|
||||
[DependsOn(typeof(WebhooksFeature))]
|
||||
public class OrchardCoreFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Module.AddVariableTypeAndAlias<ContentItemEventPayload>("ContentItemPublished", "Orchard");
|
||||
Module.AddActivitiesFrom<OrchardCoreFeature>();
|
||||
Services
|
||||
.AddActivityProvider<OrchardContentItemsEventActivityProvider>()
|
||||
.AddHandlersFrom<OrchardCoreFeature>()
|
||||
;
|
||||
}
|
||||
|
||||
public override void Apply()
|
||||
{
|
||||
Services.AddOrchardCoreClient();
|
||||
Services.AddOptions<OrchardCoreOptions>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait />
|
||||
</Weavers>
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
using Elsa.Expressions.Helpers;
|
||||
using Elsa.Mediator.Contracts;
|
||||
using Elsa.OrchardCore.Stimuli;
|
||||
using Elsa.OrchardCore.WebhookPayloads;
|
||||
using Elsa.Webhooks.Notifications;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using JetBrains.Annotations;
|
||||
using WebhooksCore;
|
||||
|
||||
namespace Elsa.OrchardCore.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes Orchard activities based on the received webhook.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class InvokeOrchardWebhookEventActivities(IStimulusSender stimulusSender) : INotificationHandler<WebhookEventReceived>
|
||||
{
|
||||
public async Task HandleAsync(WebhookEventReceived notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var webhookEvent = notification.WebhookEvent;
|
||||
var webhookEventType = webhookEvent.EventType;
|
||||
var webhookEventDescriptors = WebhookEventTypes.GetWebhookEventDescriptors().ToDictionary(x => x.WebhookEventType, x => x);
|
||||
|
||||
if(!webhookEventDescriptors.TryGetValue(webhookEventType, out var webhookEventDescriptor))
|
||||
return;
|
||||
|
||||
var eventType = webhookEventDescriptor.EventType;
|
||||
var contentItemEventPayload = (ContentItemEventPayload)webhookEvent.Payload.ConvertTo(webhookEventDescriptor.PayloadType)!;
|
||||
var contentType = contentItemEventPayload.ContentType;
|
||||
var fullTypeName = OrchardCoreActivityNameHelper.GetContentItemEventActivityFullTypeName(contentType, eventType);
|
||||
var stimulus = new ContentItemEventStimulus(contentType, eventType);
|
||||
var metadata = new StimulusMetadata
|
||||
{
|
||||
Input = new Dictionary<string, object>
|
||||
{
|
||||
[nameof(WebhookEvent)] = webhookEvent,
|
||||
[nameof(ContentItemEventPayload)] = contentItemEventPayload
|
||||
}
|
||||
};
|
||||
await stimulusSender.SendAsync(fullTypeName, stimulus, metadata, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
namespace Elsa.OrchardCore;
|
||||
|
||||
public static class OrchardCoreActivityNameHelper
|
||||
{
|
||||
public static string GetContentItemEventActivityFullTypeName(string contentType, string eventName)
|
||||
{
|
||||
return $"OrchardCore.ContentItem.{contentType}.{eventName}";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Models;
|
||||
|
||||
public class WebhookEventDescriptor
|
||||
{
|
||||
public string WebhookEventType { get; set; }
|
||||
public string EventType { get; set; }
|
||||
public Type PayloadType { get; set; }
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace Elsa.OrchardCore;
|
||||
|
||||
public class OrchardCoreOptions
|
||||
{
|
||||
public ISet<string> ContentTypes { get; set; } = new HashSet<string>();
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
namespace Elsa.OrchardCore.Stimuli;
|
||||
|
||||
public record ContentItemEventStimulus(string ContentType, string EventType);
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
using Elsa.OrchardCore.Models;
|
||||
using Elsa.OrchardCore.WebhookPayloads;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Elsa.OrchardCore;
|
||||
|
||||
[UsedImplicitly]
|
||||
public static class WebhookEventTypes
|
||||
{
|
||||
public static IEnumerable<WebhookEventDescriptor> GetWebhookEventDescriptors()
|
||||
{
|
||||
yield return GetWebhookEventDescriptor("content-item.created", "Created", typeof(ContentItemEventPayload));
|
||||
yield return GetWebhookEventDescriptor("content-item.published", "Published", typeof(ContentItemEventPayload));
|
||||
yield return GetWebhookEventDescriptor("content-item.unpublished", "Unpublished", typeof(ContentItemEventPayload));
|
||||
yield return GetWebhookEventDescriptor("content-item.removed", "Removed", typeof(ContentItemEventPayload));
|
||||
}
|
||||
|
||||
private static WebhookEventDescriptor GetWebhookEventDescriptor(string webhookEventType, string eventType, Type payloadType)
|
||||
{
|
||||
return new WebhookEventDescriptor
|
||||
{
|
||||
WebhookEventType = webhookEventType,
|
||||
EventType = eventType,
|
||||
PayloadType = payloadType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
namespace Elsa.OrchardCore.WebhookPayloads;
|
||||
|
||||
public record ContentItemEventPayload(
|
||||
string ContentType,
|
||||
string DisplayText,
|
||||
string Author,
|
||||
string Owner,
|
||||
string ContentItemId);
|
||||
Loading…
Reference in a new issue