Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Elsa.Server.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
<Project Path="src\Elsa\Agent\GitHubCopilot\Elsa.Agent.GitHubCopilot.csproj" />
<Project Path="src\Elsa\Agent\Workflows\Elsa.Agent.Workflows.csproj" />
</Folder>
<Folder Name="/src/Elsa/Attention/">
<Project Path="src/Elsa/Attention/Core/Elsa.Attention.Core.csproj" />
<Project Path="src/Elsa/Attention/Api/Elsa.Attention.Api.csproj" />
</Folder>
<Folder Name="/src/Elsa/Api/">
<Project Path="src/Elsa/Api/FastEndpoints/Elsa.Api.FastEndpoints.csproj" />
</Folder>
Expand Down Expand Up @@ -138,6 +142,7 @@
<Project Path="src/Elsa/Mediator/Elsa.Mediator.csproj" />
</Folder>
<Folder Name="/src/Elsa/Modularity/">
<Project Path="src/Elsa/Modularity/Attention/Elsa.Modularity.Attention.csproj" />
<Project Path="src/Elsa/Modularity/Api/Elsa.Modularity.Api.csproj" />
<Project Path="src/Elsa/Modularity/Core/Elsa.Modularity.Core.csproj" />
<Project Path="src/Elsa/Modularity/ExtensionBuilder/Elsa.Modularity.ExtensionBuilder.csproj" />
Expand Down Expand Up @@ -180,10 +185,18 @@
<Project Path="src/Elsa/Serialization/SystemText/Elsa.Serialization.SystemText.csproj" />
</Folder>
<Folder Name="/src/Elsa/Secrets/">
<Project Path="src/Elsa/Secrets/Attention/Elsa.Secrets.Attention.csproj" />
<Project Path="src/Elsa/Secrets/Api/Elsa.Secrets.Api.csproj" />
<Project Path="src/Elsa/Secrets/Core/Elsa.Secrets.Core.csproj" />
<Project Path="src/Elsa/Secrets/Elsa.Secrets.csproj" />
</Folder>
<Folder Name="/src/Elsa/Studio/Preferences/">
<Project Path="src/Elsa/Studio/Preferences/Core/Elsa.Studio.Preferences.Core.csproj" />
<Project Path="src/Elsa/Studio/Preferences/Api/Elsa.Studio.Preferences.Api.csproj" />
</Folder>
<Folder Name="/src/Elsa/Studio/Preferences/Persistence/">
<Project Path="src/Elsa/Studio/Preferences/Persistence/Groundwork/Elsa.Studio.Preferences.Persistence.Groundwork.csproj" />
</Folder>
<Folder Name="/src/Elsa/Secrets/Persistence/">
<Project Path="src/Elsa/Secrets/Persistence/Groundwork/Elsa.Secrets.Persistence.Groundwork.csproj" />
</Folder>
Expand All @@ -198,6 +211,12 @@
<Folder Name="/src/Elsa/Workflows/">
<Project Path="src/Elsa/Workflows/Primitives/Elsa.Workflows.Primitives.csproj" />
</Folder>
<Folder Name="/src/Elsa/Workflows/Dashboard/">
<Project Path="src/Elsa/Workflows/Dashboard/Elsa.Workflows.Dashboard.csproj" />
</Folder>
<Folder Name="/src/Elsa/Workflows/Dashboard/Persistence/">
<Project Path="src/Elsa/Workflows/Dashboard/Persistence/Groundwork/Elsa.Workflows.Dashboard.Persistence.Groundwork.csproj" />
</Folder>
<Folder Name="/src/Elsa/Workflows/Design/">
<Project Path="src/Elsa/Workflows/Design/Api/Elsa.Workflows.Design.Api.csproj" />
<Project Path="src/Elsa/Workflows/Design/Core/Elsa.Workflows.Design.Core.csproj" />
Expand Down Expand Up @@ -225,6 +244,7 @@
<Project Path="src/Elsa/Workflows/Publishing/Core/Elsa.Workflows.Publishing.Core.csproj" />
</Folder>
<Folder Name="/src/Elsa/Workflows/Runtime/">
<Project Path="src/Elsa/Workflows/Runtime/Attention/Elsa.Workflows.Runtime.Attention.csproj" />
<Project Path="src/Elsa/Workflows/Runtime/Api/Elsa.Workflows.Runtime.Api.csproj" />
<Project Path="src/Elsa/Workflows/Runtime/Core/Elsa.Workflows.Runtime.Core.csproj" />
<Project Path="src/Elsa/Workflows/Runtime/Elsa.Workflows.Runtime.csproj" />
Expand Down Expand Up @@ -330,9 +350,18 @@
<Folder Name="/tests/Elsa/Foundation/Identity/Persistence/Groundwork/">
<Project Path="tests/Elsa/Foundation/Identity/Persistence/Groundwork/Tests/Elsa.Foundation.Identity.Persistence.Groundwork.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Attention/Core/">
<Project Path="tests/Elsa/Attention/Core/Tests/Elsa.Attention.Core.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Attention/Api/">
<Project Path="tests/Elsa/Attention/Api/Tests/Elsa.Attention.Api.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Modularity/">
<Project Path="tests/Elsa/Modularity/Tests/Elsa.Modularity.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Modularity/Attention/">
<Project Path="tests/Elsa/Modularity/Attention/Tests/Elsa.Modularity.Attention.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Primitives/">
<Project Path="tests/Elsa/Primitives/Tests/Elsa.Primitives.Tests.csproj" />
</Folder>
Expand Down Expand Up @@ -370,13 +399,25 @@
<Folder Name="/tests/Elsa/Secrets/">
<Project Path="tests/Elsa/Secrets/Tests/Elsa.Secrets.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Secrets/Attention/">
<Project Path="tests/Elsa/Secrets/Attention/Tests/Elsa.Secrets.Attention.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Studio/Preferences/">
<Project Path="tests/Elsa/Studio/Preferences/Tests/Elsa.Studio.Preferences.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Studio/Preferences/Persistence/Groundwork/">
<Project Path="tests/Elsa/Studio/Preferences/Persistence/Groundwork/Tests/Elsa.Studio.Preferences.Persistence.Groundwork.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Serialization/">
<Project Path="tests/Elsa/Serialization/Tests/Elsa.Serialization.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Workflows/" />
<Folder Name="/tests/Elsa/Workflows/Design/">
<Project Path="tests/Elsa/Workflows/Design/Tests/Elsa.Workflows.Design.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Workflows/Dashboard/">
<Project Path="tests/Elsa/Workflows/Dashboard/Tests/Elsa.Workflows.Dashboard.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Workflows/Design/Api/">
<Project Path="tests/Elsa/Workflows/Design/Api/Tests/Elsa.Workflows.Design.Api.Tests.csproj" />
</Folder>
Expand All @@ -391,6 +432,9 @@
<Folder Name="/tests/Elsa/Workflows/Runtime/">
<Project Path="tests/Elsa/Workflows/Runtime/Tests/Elsa.Workflows.Runtime.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Workflows/Runtime/Attention/">
<Project Path="tests/Elsa/Workflows/Runtime/Attention/Tests/Elsa.Workflows.Runtime.Attention.Tests.csproj" />
</Folder>
<Folder Name="/tests/Elsa/Workflows/Runtime/Http/">
<Project Path="tests/Elsa/Workflows/Runtime/Http/Tests/Elsa.Workflows.Runtime.Http.Tests.csproj" />
</Folder>
Expand Down
10 changes: 10 additions & 0 deletions src/Apps/Elsa.Server/Elsa.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
<ProjectReference Include="..\..\Elsa\Agent\Api\Elsa.Agent.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Agent\GitHubCopilot\Elsa.Agent.GitHubCopilot.csproj" />
<ProjectReference Include="..\..\Elsa\Agent\Workflows\Elsa.Agent.Workflows.csproj" />
<ProjectReference Include="..\..\Elsa\Attention\Core\Elsa.Attention.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Attention\Api\Elsa.Attention.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Activities\Design\Api\Elsa.Activities.Design.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Activities\Design\Core\Elsa.Activities.Design.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Activities\Design\Persistence\Core\Elsa.Activities.Design.Persistence.Core.csproj" />
Expand Down Expand Up @@ -71,9 +73,13 @@
<ProjectReference Include="..\..\Elsa\Foundation\Identity\Oidc\Elsa.Foundation.Identity.Oidc.csproj" />
<ProjectReference Include="..\..\Elsa\Foundation\Identity\OpenIddict\Elsa.Foundation.Identity.OpenIddict.csproj" />
<ProjectReference Include="..\..\Elsa\Secrets\Persistence\Groundwork\Elsa.Secrets.Persistence.Groundwork.csproj" />
<ProjectReference Include="..\..\Elsa\Secrets\Attention\Elsa.Secrets.Attention.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Dashboard\Elsa.Workflows.Dashboard.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Dashboard\Persistence\Groundwork\Elsa.Workflows.Dashboard.Persistence.Groundwork.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Design\JavaScript\Elsa.Workflows.Design.JavaScript.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Publishing\Api\Elsa.Workflows.Publishing.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Runtime\Api\Elsa.Workflows.Runtime.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Workflows\Runtime\Attention\Elsa.Workflows.Runtime.Attention.csproj" />
<ProjectReference Include="..\..\Elsa\Caching\Core\Elsa.Caching.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Caching\Memory\Elsa.Caching.Memory.csproj" />
<ProjectReference Include="..\..\Elsa\Diagnostics\ConsoleLogStreaming\Elsa.Diagnostics.ConsoleLogStreaming.csproj" />
Expand All @@ -87,6 +93,7 @@
<ProjectReference Include="..\..\Elsa\Mediator\Core\Elsa.Mediator.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Mediator\Elsa.Mediator.csproj" />
<ProjectReference Include="..\..\Elsa\Modularity\Api\Elsa.Modularity.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Modularity\Attention\Elsa.Modularity.Attention.csproj" />
<ProjectReference Include="..\..\Elsa\Modularity\Core\Elsa.Modularity.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Modularity\ExtensionBuilder\Elsa.Modularity.ExtensionBuilder.csproj" />
<ProjectReference Include="..\..\Elsa\Modularity\Nuplane\Elsa.Modularity.Nuplane.csproj" />
Expand All @@ -99,6 +106,9 @@
<ProjectReference Include="..\..\Elsa\Serialization\Core\Elsa.Serialization.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Serialization\Newtonsoft\Elsa.Serialization.Newtonsoft.csproj" />
<ProjectReference Include="..\..\Elsa\Serialization\SystemText\Elsa.Serialization.SystemText.csproj" />
<ProjectReference Include="..\..\Elsa\Studio\Preferences\Core\Elsa.Studio.Preferences.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Studio\Preferences\Api\Elsa.Studio.Preferences.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Studio\Preferences\Persistence\Groundwork\Elsa.Studio.Preferences.Persistence.Groundwork.csproj" />
<ProjectReference Include="..\..\Elsa\Secrets\Api\Elsa.Secrets.Api.csproj" />
<ProjectReference Include="..\..\Elsa\Secrets\Core\Elsa.Secrets.Core.csproj" />
<ProjectReference Include="..\..\Elsa\Secrets\Elsa.Secrets.csproj" />
Expand Down
17 changes: 17 additions & 0 deletions src/Apps/Elsa.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,17 @@
using Elsa.Primitives.Hosting;
using Elsa.Serialization.Newtonsoft;
using Elsa.Serialization.SystemText;
using Elsa.Attention.Api;
using Elsa.Modularity.Attention;
using Elsa.Secrets.Attention;
using Elsa.Studio.Preferences.Api;
using Elsa.Studio.Preferences.Core;
using Elsa.Studio.Preferences.Persistence.Groundwork;
using Elsa.Tasks;
using Elsa.Workflows.Design.Api;
using Elsa.Workflows.Dashboard;
using Elsa.Workflows.Publishing.Api;
using Elsa.Workflows.Runtime.Attention;
using Elsa.Workflows.Runtime.Api;
using Elsa.Workflows.Runtime.Core.Models;
using Elsa.Workflows.Runtime.Http;
Expand Down Expand Up @@ -245,8 +253,17 @@

typeof(OpenIddictIdentityFeature).Assembly,
typeof(ApiSecurityFeature).Assembly,
typeof(AttentionApiFeature).Assembly,

typeof(StudioPreferencesFeature).Assembly,
typeof(StudioPreferencesApiFeature).Assembly,
typeof(StudioPreferencesGroundworkPersistenceFeature).Assembly,
typeof(WorkflowsDashboardFeature).Assembly,

typeof(ModularityApiFeature).Assembly,
typeof(ModularityAttentionFeature).Assembly,
typeof(SecretsAttentionFeature).Assembly,
typeof(WorkflowsRuntimeAttentionFeature).Assembly,
typeof(StructuredLogsFeature).Assembly,
typeof(SqliteStructuredLogsPersistenceShellFeature).Assembly,
typeof(OpenTelemetryFeature).Assembly
Expand Down
7 changes: 7 additions & 0 deletions src/Apps/Elsa.Server/shells.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,18 @@
"SampleNuplaneActivities": {},
"Secrets": {},
"SecretsApi": {},
"SecretsAttention": {},
"SecretsGroundworkPersistence": {},
"Serialization": {},
"AttentionApi": {},
"ModularityAttention": {},
"StudioPreferences": {},
"StudioPreferencesApi": {},
"Tasks": {},
"WeatherForecastSample": {},
"WorkflowsDesignApi": {},
"WorkflowsDashboard": {},
"WorkflowsRuntimeAttention": {},
"WorkflowsDesignPersistenceEFCoreSqlite": {},
"WorkflowsPublishingApi": {},
"WorkflowsRuntimeApi": {},
Expand Down
21 changes: 21 additions & 0 deletions src/Elsa/Attention/Api/AttentionApiFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using CShells.Features;
using Elsa.Api.FastEndpoints;
using Elsa.Platform.PackageManifest.Generator.Hints;
using Microsoft.Extensions.DependencyInjection;

namespace Elsa.Attention.Api;

[ManifestRuntimeKind(ElsaRuntimeKinds.Server)]
[ManifestFeatureCategory("Attention")]
[ShellFeature(
name: "AttentionApi",
DisplayName = "Attention API",
Description = "Aggregates permission-scoped attention contributors through a shared query endpoint.")]
public sealed class AttentionApiFeature : FastEndpointsFeatureBase
{
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
services.AddAttentionCore();
}
}
6 changes: 6 additions & 0 deletions src/Elsa/Attention/Api/AttentionRoutes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Elsa.Attention.Api;

public static class AttentionRoutes
{
public const string Items = "/_elsa/attention/items";
}
45 changes: 45 additions & 0 deletions src/Elsa/Attention/Api/AttentionServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Elsa.Attention.Core;
using Elsa.Foundation.Identity.Abstractions.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace Elsa.Attention.Api;

public static class AttentionServiceCollectionExtensions
{
public static IServiceCollection AddAttentionCore(
this IServiceCollection services,
Action<AttentionOptions>? configure = null)
{
var options = services.AddOptions<AttentionOptions>();
if (configure is not null)
options.Configure(configure);

services.TryAddScoped<IAttentionPermissionEvaluator, FoundationAttentionPermissionEvaluator>();
services.TryAddScoped<IAttentionContributorRegistry>(provider =>
new AttentionContributorRegistry(provider.GetServices<IAttentionContributor>()));
services.TryAddScoped<IAttentionAggregationService>(provider =>
new AttentionAggregationService(
provider.GetRequiredService<IAttentionContributorRegistry>(),
provider.GetRequiredService<IAttentionPermissionEvaluator>(),
provider.GetRequiredService<IOptions<AttentionOptions>>().Value));
return services;
}

private sealed class FoundationAttentionPermissionEvaluator(IPermissionEvaluator evaluator)
: IAttentionPermissionEvaluator
{
public async ValueTask<bool> IsAllowedAsync(
System.Security.Claims.ClaimsPrincipal principal,
string permission,
string? tenantId,
CancellationToken cancellationToken = default)
{
var result = await evaluator.EvaluateAsync(
new PermissionEvaluationContext(principal, permission, tenantId),
cancellationToken);
return result.Succeeded;
}
}
}
24 changes: 24 additions & 0 deletions src/Elsa/Attention/Api/Elsa.Attention.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CShells.Abstractions" />
<PackageReference Include="Elsa.Platform.PackageManifest.Generator" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Core\Elsa.Attention.Core.csproj" />
<ProjectReference Include="..\..\Api\FastEndpoints\Elsa.Api.FastEndpoints.csproj" />
<ProjectReference Include="..\..\Foundation\Identity\Abstractions\Elsa.Foundation.Identity.Abstractions.csproj" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions src/Elsa/Attention/Api/Endpoints/GetAttentionItems.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Elsa.Api.FastEndpoints.Abstractions;
using Elsa.Attention.Core;
using Elsa.Foundation.Identity.Abstractions.Authorization;
using Microsoft.AspNetCore.Http;

namespace Elsa.Attention.Api.Endpoints;

internal sealed class GetAttentionItems(IAttentionAggregationService aggregationService)
: ElsaEndpointWithoutRequest<AttentionAggregationResult>
{
public override void Configure()
{
Get(AttentionRoutes.Items);
ConfigurePermissions();
}

public override async Task HandleAsync(CancellationToken cancellationToken)
{
var contributorIds = HttpContext.Request.Query["contributorId"]
.Select(value => value ?? string.Empty)
.ToArray();
var context = new AttentionQueryContext(
HttpContext.User,
HttpContext.User.FindFirst(IdentityClaimTypes.TenantId)?.Value);

try
{
var response = await aggregationService.AggregateAsync(
new AttentionQuery(context, contributorIds.Length == 0 ? null : contributorIds),
cancellationToken);
await Send.OkAsync(response, cancellationToken);
}
catch (AttentionQueryException exception)
{
await Send.StringAsync(
exception.Message,
StatusCodes.Status400BadRequest,
cancellation: cancellationToken);
}
}
}
Loading
Loading