40 changed files with 1137 additions and 100 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<AssemblyName>LINGYUN.Abp.ElsaNext.Server</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.ElsaNext.Server</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
<Nullable>Enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Elsa" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.CSharp" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Scheduling" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Workflows.Api" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.ElsaNext\LINGYUN.Abp.ElsaNext.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,41 @@ |
|||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Features.Services; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Server; |
||||
|
|
||||
|
[DependsOn(typeof(AbpElsaNextModule))] |
||||
|
public class AbpElsaNextServerModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IModule>(elsa => |
||||
|
{ |
||||
|
// see: https://v3.elsaworkflows.io/docs/installation/elsa-server
|
||||
|
|
||||
|
// Expose Elsa API endpoints.
|
||||
|
elsa.UseWorkflowsApi(); |
||||
|
|
||||
|
// Setup a SignalR hub for real-time updates from the server.
|
||||
|
elsa.UseRealTimeWorkflows(); |
||||
|
|
||||
|
// Enable C# workflow expressions
|
||||
|
elsa.UseCSharp(); |
||||
|
|
||||
|
// Enable Liquid workflow expressions.
|
||||
|
elsa.UseLiquid(); |
||||
|
|
||||
|
// Enable HTTP activities.
|
||||
|
elsa.UseHttp(); |
||||
|
|
||||
|
// Use timer activities.
|
||||
|
elsa.UseScheduling(); |
||||
|
|
||||
|
// Register custom activities from the application, if any.
|
||||
|
elsa.AddActivitiesFrom<AbpElsaNextServerModule>(); |
||||
|
|
||||
|
// Register custom workflows from the application, if any.
|
||||
|
elsa.AddWorkflowsFrom<AbpElsaNextServerModule>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<AssemblyName>LINGYUN.Abp.ElsaNext</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.ElsaNext</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
<Nullable>Enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AutoMapper" /> |
||||
|
<PackageReference Include="Volo.Abp.Features" /> |
||||
|
<PackageReference Include="Volo.Abp.Guids" /> |
||||
|
<PackageReference Include="Volo.Abp.Timing" /> |
||||
|
<PackageReference Include="Volo.Abp.Threading" /> |
||||
|
<PackageReference Include="Volo.Abp.Json" /> |
||||
|
<!--<PackageReference Include="Elsa" VersionOverride="$(ElsaNextPackageVersion)" />--> |
||||
|
<PackageReference Include="Elsa" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Elsa.Workflows; |
||||
|
using Volo.Abp.Guids; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext; |
||||
|
|
||||
|
public class AbpElsaIdentityGenerator : IIdentityGenerator |
||||
|
{ |
||||
|
private readonly IGuidGenerator _guidGenerator; |
||||
|
|
||||
|
public AbpElsaIdentityGenerator(IGuidGenerator guidGenerator) |
||||
|
{ |
||||
|
_guidGenerator = guidGenerator; |
||||
|
} |
||||
|
|
||||
|
public string GenerateId() |
||||
|
{ |
||||
|
return _guidGenerator.Create().ToString("N"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using AutoMapper; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext; |
||||
|
public class AbpElsaNextAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public AbpElsaNextAutoMapperProfile() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
using Elsa.Common.Features; |
||||
|
using Elsa.Common.Multitenancy; |
||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Features.Services; |
||||
|
using Elsa.Tenants.Extensions; |
||||
|
using Elsa.Workflows; |
||||
|
using LINGYUN.Abp.ElsaNext.Localization; |
||||
|
using LINGYUN.Abp.ElsaNext.Multitenancy; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Features; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAutoMapperModule), |
||||
|
typeof(AbpFeaturesModule), |
||||
|
typeof(AbpThreadingModule), |
||||
|
typeof(AbpJsonModule))] |
||||
|
public class AbpElsaNextModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddScoped<ITenantResolver, AbpTenantResolver>(); |
||||
|
|
||||
|
var elsaModule = context.Services.GetPreConfigureActions<IModule>(); |
||||
|
|
||||
|
context.Services.AddElsa(elsa => |
||||
|
{ |
||||
|
elsa |
||||
|
.AddActivitiesFrom<AbpElsaNextModule>() |
||||
|
.AddWorkflowsFrom<AbpElsaNextModule>() |
||||
|
.UseTenants(tenants => |
||||
|
{ |
||||
|
tenants.ConfigureMultitenancy(options => |
||||
|
{ |
||||
|
options.TenantResolverPipelineBuilder.Append<AbpTenantResolver>(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
elsa.Configure<MultitenancyFeature>(feature => |
||||
|
{ |
||||
|
feature.UseTenantsProvider<AbpTenantsProvider>(); |
||||
|
}); |
||||
|
|
||||
|
elsaModule.Configure(elsa); |
||||
|
}); |
||||
|
|
||||
|
context.Services.Replace( |
||||
|
ServiceDescriptor.Singleton<IIdentityGenerator, AbpElsaIdentityGenerator>()); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources.Add<ElsaNextResource>("en"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("ElsaNext")] |
||||
|
public class ElsaNextResource |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Elsa.Common.Multitenancy; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Multitenancy; |
||||
|
public class AbpTenantResolver(ITenantConfigurationProvider tenantConfigurationProvider) : TenantResolverBase |
||||
|
{ |
||||
|
protected async override Task<TenantResolverResult> ResolveAsync(TenantResolverContext context) |
||||
|
{ |
||||
|
var tenant = await tenantConfigurationProvider.GetAsync(); |
||||
|
if (tenant == null) |
||||
|
{ |
||||
|
return Unresolved(); |
||||
|
} |
||||
|
|
||||
|
return AutoResolve(tenant.Id.ToString()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Elsa.Common.Multitenancy; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Multitenancy; |
||||
|
public class AbpTenantsProvider : ITenantsProvider |
||||
|
{ |
||||
|
private readonly ITenantStore _tenantStore; |
||||
|
public AbpTenantsProvider(ITenantStore tenantStore) |
||||
|
{ |
||||
|
_tenantStore = tenantStore; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<Tenant?> FindAsync(TenantFilter filter, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (Guid.TryParse(filter.Id, out var tenantId)) |
||||
|
{ |
||||
|
var tenant = await _tenantStore.FindAsync(tenantId); |
||||
|
return tenant != null ? new Tenant |
||||
|
{ |
||||
|
Id = tenant.Id.ToString(), |
||||
|
Name = tenant.Name, |
||||
|
} : null; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<IEnumerable<Tenant>> ListAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var tenants = await _tenantStore.GetListAsync(); |
||||
|
|
||||
|
return tenants.Select(tenant => new Tenant |
||||
|
{ |
||||
|
Id = tenant.Id.ToString(), |
||||
|
Name = tenant.Name |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
# LINGYUN.Abp.ElsaNext |
||||
|
|
||||
|
[elsa-core](https://github.com/elsa-workflows/elsa-core) 工作流的abp集成(3.x版本) |
||||
|
|
||||
|
## 特性 |
||||
|
|
||||
|
* 定义**AbpTenantResolver**与多租户集成,使elsa支持abp租户解析 |
||||
|
* 定义**AbpTenantsProvider**与多租户集成,使elsa从abp中取租户信息 |
||||
|
* 定义**AbpElsaIdGenerator**通过**IGuidGenerator**接口生成工作流标识 |
||||
|
* 定义**abp**相关JavaScript扩展 |
||||
|
|
||||
|
## 配置使用 |
||||
|
|
||||
|
```csharp |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpElsaNextModule) |
||||
|
)] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IModule>(elsa => |
||||
|
{ |
||||
|
// 自定义elsa相关配置 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
@ -0,0 +1 @@ |
|||||
|
elsa.sqlite.* |
||||
@ -0,0 +1,113 @@ |
|||||
|
using Elsa.Expressions.Helpers; |
||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Workflows; |
||||
|
using Elsa.Workflows.Memory; |
||||
|
using Elsa.Workflows.Models; |
||||
|
using Humanizer; |
||||
|
using System.Text.Json; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next; |
||||
|
|
||||
|
public class AbpActivityFactory : IActivityFactory |
||||
|
{ |
||||
|
public IActivity Create(Type type, ActivityConstructorContext context) |
||||
|
{ |
||||
|
// Backwards compatibility for older JSON schemas.
|
||||
|
var canStartWorkflow = GetBoolean(context.Element, "canStartWorkflow"); |
||||
|
var runAsynchronously = GetBoolean(context.Element, "runAsynchronously"); |
||||
|
var activityElement = context.Element; |
||||
|
var activityDescriptor = context.ActivityDescriptor; |
||||
|
var activity = (IActivity)context.Element.Deserialize(type, context.SerializerOptions)!; |
||||
|
var composite = activity as IComposite; |
||||
|
|
||||
|
composite?.Setup(); |
||||
|
|
||||
|
// TODO: 反序列化未创建默认值?
|
||||
|
if (activityDescriptor != null) |
||||
|
{ |
||||
|
ReadSyntheticInputs(activityDescriptor, activity, activityElement, context.SerializerOptions); |
||||
|
ReadSyntheticOutputs(activityDescriptor, activity, activityElement); |
||||
|
} |
||||
|
|
||||
|
activity.SetCanStartWorkflow(canStartWorkflow); |
||||
|
activity.SetRunAsynchronously(runAsynchronously); |
||||
|
|
||||
|
return activity; |
||||
|
} |
||||
|
|
||||
|
private void ReadSyntheticInputs(ActivityDescriptor activityDescriptor, IActivity activity, JsonElement activityRoot, JsonSerializerOptions options) |
||||
|
{ |
||||
|
foreach (var inputDescriptor in activityDescriptor.Inputs.Where(x => x.IsSynthetic)) |
||||
|
{ |
||||
|
var inputName = inputDescriptor.Name; |
||||
|
var propertyName = inputName.Camelize(); |
||||
|
var nakedType = inputDescriptor.Type; |
||||
|
var wrappedType = typeof(Input<>).MakeGenericType(nakedType); |
||||
|
|
||||
|
if (!activityRoot.TryGetProperty(propertyName, out var propertyElement) || propertyElement.ValueKind == JsonValueKind.Null || propertyElement.ValueKind == JsonValueKind.Undefined) |
||||
|
continue; |
||||
|
|
||||
|
var isWrapped = propertyElement.ValueKind == JsonValueKind.Object && propertyElement.GetProperty("typeName").ValueKind != JsonValueKind.Undefined; |
||||
|
|
||||
|
if (isWrapped) |
||||
|
{ |
||||
|
var json = propertyElement.ToString(); |
||||
|
var inputValue = JsonSerializer.Deserialize(json, wrappedType, options); |
||||
|
|
||||
|
activity.SyntheticProperties[inputName] = inputValue!; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
activity.SyntheticProperties[inputName] = propertyElement.ConvertTo(inputDescriptor.Type)!; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ReadSyntheticOutputs(ActivityDescriptor activityDescriptor, IActivity activity, JsonElement activityRoot) |
||||
|
{ |
||||
|
foreach (var outputDescriptor in activityDescriptor.Outputs.Where(x => x.IsSynthetic)) |
||||
|
{ |
||||
|
var outputName = outputDescriptor.Name; |
||||
|
var propertyName = outputName.Camelize(); |
||||
|
var nakedType = outputDescriptor.Type; |
||||
|
var wrappedType = typeof(Output<>).MakeGenericType(nakedType); |
||||
|
|
||||
|
if (!activityRoot.TryGetProperty(propertyName, out var propertyElement) || propertyElement.ValueKind == JsonValueKind.Null || propertyElement.ValueKind == JsonValueKind.Undefined) |
||||
|
continue; |
||||
|
|
||||
|
var memoryReferenceElement = propertyElement.GetProperty("memoryReference"); |
||||
|
|
||||
|
if (!memoryReferenceElement.TryGetProperty("id", out var memoryReferenceIdElement)) |
||||
|
continue; |
||||
|
|
||||
|
var variable = new Variable |
||||
|
{ |
||||
|
Id = memoryReferenceIdElement.GetString()! |
||||
|
}; |
||||
|
variable.Name = variable.Id; |
||||
|
|
||||
|
var output = Activator.CreateInstance(wrappedType, variable)!; |
||||
|
|
||||
|
activity.SyntheticProperties[outputName] = output!; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static bool GetBoolean(JsonElement element, string propertyName) |
||||
|
{ |
||||
|
var propertyNames = new[] { propertyName.Camelize(), propertyName.Pascalize() }; |
||||
|
|
||||
|
foreach (var name in propertyNames) |
||||
|
{ |
||||
|
if (element.TryGetProperty("customProperties", out var customPropertyElement)) |
||||
|
{ |
||||
|
if (customPropertyElement.TryGetProperty(name, out var canStartWorkflowElement)) |
||||
|
return canStartWorkflowElement.GetBoolean(); |
||||
|
} |
||||
|
|
||||
|
if (element.TryGetProperty(propertyName.Camelize(), out var property) && property.GetBoolean()) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using Elsa.Studio.Localization.Services; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using System.Globalization; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next; |
||||
|
|
||||
|
public class AbpBlazorServerCultureService(NavigationManager navigationManager) : ICultureService |
||||
|
{ |
||||
|
public Task ChangeCultureAsync(CultureInfo culture) |
||||
|
{ |
||||
|
if (CultureInfo.CurrentUICulture.Name != culture.Name) |
||||
|
{ |
||||
|
var cultureString = culture.Name; |
||||
|
var uri = new Uri(navigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped); |
||||
|
|
||||
|
// Set culture of the current thread.
|
||||
|
CultureInfo.CurrentCulture = culture; |
||||
|
CultureInfo.CurrentUICulture = culture; |
||||
|
var cultureEscaped = Uri.EscapeDataString(cultureString); |
||||
|
// var uriEscaped = Uri.EscapeDataString(uri);
|
||||
|
|
||||
|
navigationManager.NavigateTo( |
||||
|
$"Culture/Set?culture={cultureEscaped}&redirectUri=/", |
||||
|
forceLoad: true); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next.Controllers; |
||||
|
|
||||
|
public class HomeController : AbpControllerBase |
||||
|
{ |
||||
|
public IActionResult Index() |
||||
|
{ |
||||
|
return Redirect("/swagger/index.html"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<RootNamespace>LY.MicroService.WorkflowManagement.Next</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="AgileConfig.Client" /> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" /> |
||||
|
<!--<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" />--> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" /> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" /> |
||||
|
<!--<PackageReference Include="Volo.Abp.AspNetCore.Mvc.NewtonsoftJson" />--> |
||||
|
<PackageReference Include="Volo.Abp.Autofac" /> |
||||
|
<PackageReference Include="Volo.Abp.Json" /> |
||||
|
<PackageReference Include="Volo.Abp.Swashbuckle" /> |
||||
|
<PackageReference Include="Volo.Abp.MailKit" /> |
||||
|
<!--<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" />--> |
||||
|
<!--<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" /> |
||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" /> |
||||
|
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" />--> |
||||
|
<!--<PackageReference Include="Microsoft.CodeAnalysis.Common" /> |
||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" /> |
||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"> |
||||
|
<PrivateAssets>all</PrivateAssets> |
||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |
||||
|
</PackageReference>--> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Serilog.AspNetCore" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Environment" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Assembly" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Process" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Thread" /> |
||||
|
<PackageReference Include="Serilog.Settings.Configuration" /> |
||||
|
<PackageReference Include="Serilog.Sinks.Elasticsearch" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Elsa.EntityFrameworkCore" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.EntityFrameworkCore.Sqlite" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Identity" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Studio" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Studio.Core.BlazorServer" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Studio.Login.BlazorServer" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Studio.Localization.BlazorServer" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Studio.Translations" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
<PackageReference Include="Elsa.Api.Client" VersionOverride="$(ElsaNextPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\modules\elsa\LINGYUN.Abp.ElsaNext.Server\LINGYUN.Abp.ElsaNext.Server.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,61 @@ |
|||||
|
@page "/" |
||||
|
@namespace LY.MicroService.WorkflowManagement.Next.Pages |
||||
|
|
||||
|
@inject IConfiguration Configuration; |
||||
|
@{ |
||||
|
var baseUrl = $"{Request.Scheme}://{Request.Host}"; |
||||
|
var apiUrl = baseUrl + Url.Content("~/elsa/api"); |
||||
|
var basePath = ""; |
||||
|
} |
||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="utf-8" /> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||
|
<base href="~/" /> |
||||
|
<link rel="apple-touch-icon" sizes="180x180" href="@basePath/_content/Elsa.Studio.Shell/apple-touch-icon.png"> |
||||
|
<link rel="icon" type="image/png" sizes="32x32" href="@basePath/_content/Elsa.Studio.Shell/favicon-32x32.png"> |
||||
|
<link rel="icon" type="image/png" sizes="16x16" href="@basePath/_content/Elsa.Studio.Shell/favicon-16x16.png"> |
||||
|
<link rel="manifest" href="@basePath/_content/Elsa.Studio.Shell/site.webmanifest"> |
||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"> |
||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
||||
|
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" /> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet"> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet"> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Grandstander:wght@100&display=swap" rel="stylesheet"> |
||||
|
<link href="@basePath/_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" /> |
||||
|
<link href="@basePath/_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet" /> |
||||
|
<link href="@basePath/_content/Radzen.Blazor/css/material-base.css" rel="stylesheet"> |
||||
|
<link href="@basePath/_content/Elsa.Studio.Shell/css/shell.css" rel="stylesheet"> |
||||
|
<link href="LY.MicroService.WorkflowManagement.Next.HttpApi.Host.styles.css" rel="stylesheet"> |
||||
|
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" /> |
||||
|
</head> |
||||
|
<body> |
||||
|
<component type="typeof(App)" render-mode="ServerPrerendered" /> |
||||
|
|
||||
|
<div id="blazor-error-ui"> |
||||
|
<environment include="Staging,Production"> |
||||
|
An error has occurred. This application may no longer respond until reloaded. |
||||
|
</environment> |
||||
|
<environment include="Development"> |
||||
|
An unhandled exception has occurred. See browser dev tools for details. |
||||
|
</environment> |
||||
|
<a href="" class="reload">Reload</a> |
||||
|
<a class="dismiss">🗙</a> |
||||
|
</div> |
||||
|
<script src="@basePath/_content/BlazorMonaco/jsInterop.js"></script> |
||||
|
<script src="@basePath/_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script> |
||||
|
<script src="@basePath/_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script> |
||||
|
<script src="@basePath/_content/MudBlazor/MudBlazor.min.js"></script> |
||||
|
<script src="@basePath/_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script> |
||||
|
<script src="@basePath/_content/Radzen.Blazor/Radzen.Blazor.js"></script> |
||||
|
<script> |
||||
|
window.getClientConfig = function() { return { |
||||
|
"apiUrl": "@apiUrl", |
||||
|
"basePath": "@basePath" |
||||
|
} }; |
||||
|
</script> |
||||
|
<script src="@basePath/_framework/blazor.server.js"></script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next.Pages |
||||
|
{ |
||||
|
public class _HostModel : PageModel |
||||
|
{ |
||||
|
public void OnGet() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
@using Elsa.Studio.Shell |
||||
|
@using Microsoft.Extensions.Configuration |
||||
|
@using Microsoft.AspNetCore.Components.Web |
||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
||||
@ -0,0 +1,89 @@ |
|||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Studio.Contracts; |
||||
|
using Elsa.Studio.Localization.BlazorServer.Extensions; |
||||
|
using LY.MicroService.WorkflowManagement.Next; |
||||
|
using Serilog; |
||||
|
using Volo.Abp.IO; |
||||
|
using Volo.Abp.Modularity.PlugIns; |
||||
|
|
||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
|
||||
|
builder.Host.AddAppSettingsSecretsJson() |
||||
|
.UseAutofac() |
||||
|
.ConfigureAppConfiguration((context, config) => |
||||
|
{ |
||||
|
var agileConfigEnabled = context.Configuration["AgileConfig:IsEnabled"]; |
||||
|
if (context.Configuration.GetSection("AgileConfig").Exists() && |
||||
|
(agileConfigEnabled.IsNullOrWhiteSpace() || bool.Parse(agileConfigEnabled))) |
||||
|
{ |
||||
|
config.AddAgileConfig(new AgileConfig.Client.ConfigClient(context.Configuration)); |
||||
|
} |
||||
|
}) |
||||
|
.UseSerilog((context, provider, config) => |
||||
|
{ |
||||
|
config.ReadFrom.Configuration(context.Configuration); |
||||
|
}); |
||||
|
|
||||
|
await builder.AddApplicationAsync<WorkflowManagementNextHttpApiHostModule>(options => |
||||
|
{ |
||||
|
options.ApplicationName = "AbpElsaNextWebModule"; |
||||
|
// 从环境变量取用户机密配置, 适用于容器测试
|
||||
|
options.Configuration.UserSecretsId = Environment.GetEnvironmentVariable("APPLICATION_USER_SECRETS_ID"); |
||||
|
// 如果容器没有指定用户机密, 从项目读取
|
||||
|
options.Configuration.UserSecretsAssembly = typeof(WorkflowManagementNextHttpApiHostModule).Assembly; |
||||
|
// 搜索 Modules 目录下所有文件作为插件
|
||||
|
// 取消显示引用所有其他项目的模块,改为通过插件的形式引用
|
||||
|
var pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Modules"); |
||||
|
|
||||
|
DirectoryHelper.CreateIfNotExists(pluginFolder); |
||||
|
|
||||
|
options.PlugInSources.AddFolder(pluginFolder, SearchOption.AllDirectories); |
||||
|
}); |
||||
|
|
||||
|
// Build the web application.
|
||||
|
var app = builder.Build(); |
||||
|
|
||||
|
await app.InitializeApplicationAsync(); |
||||
|
|
||||
|
// Run each startup task.
|
||||
|
var startupTaskRunner = app.Services.GetRequiredService<IStartupTaskRunner>(); |
||||
|
await startupTaskRunner.RunStartupTasksAsync(); |
||||
|
|
||||
|
// Configure web application's middleware pipeline.
|
||||
|
// Configure the HTTP request pipeline.
|
||||
|
if (!app.Environment.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseResponseCompression(); |
||||
|
|
||||
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
|
app.UseHsts(); |
||||
|
} |
||||
|
|
||||
|
app.UseCors(); |
||||
|
app.UseForwardedHeaders(); |
||||
|
app.UseCorrelationId(); |
||||
|
app.UseElsaLocalization(); |
||||
|
app.UseStaticFiles(); |
||||
|
app.UseRouting(); // Required for SignalR.
|
||||
|
app.UseAuthentication(); |
||||
|
app.UseJwtTokenMiddleware(); |
||||
|
app.UseMultiTenancy(); |
||||
|
app.UseDynamicClaims(); |
||||
|
app.UseAuthorization(); |
||||
|
app.MapBlazorHub(); |
||||
|
app.UseWorkflowsApi(); // Use Elsa API endpoints.
|
||||
|
app.UseWorkflows(); // Use Elsa middleware to handle HTTP requests mapped to HTTP Endpoint activities.
|
||||
|
app.UseWorkflowsSignalRHubs(); // Optional SignalR integration. Elsa Studio uses SignalR to receive real-time updates from the server.
|
||||
|
app.UseSwagger(); |
||||
|
app.UseSwaggerUI(options => |
||||
|
{ |
||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API"); |
||||
|
}); |
||||
|
|
||||
|
app.UseAuditing(); |
||||
|
app.UseAbpSerilogEnrichers(); |
||||
|
app.UseConfiguredEndpoints(); |
||||
|
|
||||
|
app.MapFallbackToPage("/_Host"); |
||||
|
|
||||
|
await app.RunAsync(); |
||||
@ -0,0 +1,22 @@ |
|||||
|
{ |
||||
|
"$schema": "http://json.schemastore.org/launchsettings.json", |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:36683", |
||||
|
"sslPort": 0 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"http": { |
||||
|
"commandName": "Project", |
||||
|
"dotnetRunMessages": true, |
||||
|
"launchBrowser": false, |
||||
|
"applicationUrl": "http://127.0.0.1:30036", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.OpenApi.Models; |
||||
|
using Swashbuckle.AspNetCore.SwaggerGen; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next; |
||||
|
|
||||
|
public class TenantHeaderParamter : IOperationFilter |
||||
|
{ |
||||
|
private readonly AbpMultiTenancyOptions _multiTenancyOptions; |
||||
|
private readonly AbpAspNetCoreMultiTenancyOptions _aspNetCoreMultiTenancyOptions; |
||||
|
public TenantHeaderParamter( |
||||
|
IOptions<AbpMultiTenancyOptions> multiTenancyOptions, |
||||
|
IOptions<AbpAspNetCoreMultiTenancyOptions> aspNetCoreMultiTenancyOptions) |
||||
|
{ |
||||
|
_multiTenancyOptions = multiTenancyOptions.Value; |
||||
|
_aspNetCoreMultiTenancyOptions = aspNetCoreMultiTenancyOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context) |
||||
|
{ |
||||
|
if (_multiTenancyOptions.IsEnabled) |
||||
|
{ |
||||
|
operation.Parameters = operation.Parameters ?? new List<OpenApiParameter>(); |
||||
|
operation.Parameters.Add(new OpenApiParameter |
||||
|
{ |
||||
|
Name = _aspNetCoreMultiTenancyOptions.TenantKey, |
||||
|
In = ParameterLocation.Header, |
||||
|
Description = "Tenant Id/Name in http header", |
||||
|
Required = false |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,147 @@ |
|||||
|
using Elsa.EntityFrameworkCore.Extensions; |
||||
|
using Elsa.EntityFrameworkCore.Modules.Management; |
||||
|
using Elsa.EntityFrameworkCore.Modules.Runtime; |
||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Features.Services; |
||||
|
using Elsa.Studio.Dashboard.Extensions; |
||||
|
using Elsa.Studio.Extensions; |
||||
|
using Elsa.Studio.Localization.BlazorServer.Extensions; |
||||
|
using Elsa.Studio.Localization.BlazorServer.Services; |
||||
|
using Elsa.Studio.Localization.Models; |
||||
|
using Elsa.Studio.Localization.Services; |
||||
|
using Elsa.Studio.Login.BlazorServer.Extensions; |
||||
|
using Elsa.Studio.Login.HttpMessageHandlers; |
||||
|
using Elsa.Studio.Models; |
||||
|
using Elsa.Studio.Shell.Extensions; |
||||
|
using Elsa.Studio.Translations; |
||||
|
using Elsa.Studio.Workflows.Designer.Extensions; |
||||
|
using Elsa.Studio.Workflows.Extensions; |
||||
|
using Elsa.Workflows; |
||||
|
using LINGYUN.Abp.ElsaNext.Server; |
||||
|
using Microsoft.OpenApi.Models; |
||||
|
using Volo.Abp.AspNetCore.Authentication.JwtBearer; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
using Volo.Abp.AspNetCore.Serilog; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.MailKit; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Swashbuckle; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement.Next; |
||||
|
|
||||
|
[DependsOn(typeof(AbpElsaNextServerModule))] |
||||
|
[DependsOn(typeof(AbpAspNetCoreSerilogModule))] |
||||
|
[DependsOn(typeof(AbpAspNetCoreMultiTenancyModule))] |
||||
|
[DependsOn(typeof(AbpAspNetCoreAuthenticationJwtBearerModule))] |
||||
|
[DependsOn(typeof(AbpJsonModule))] |
||||
|
[DependsOn(typeof(AbpSwashbuckleModule))] |
||||
|
[DependsOn(typeof(AbpMailKitModule))] |
||||
|
[DependsOn(typeof(AbpAutofacModule))] |
||||
|
public class WorkflowManagementNextHttpApiHostModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IModule>(elsa => |
||||
|
{ |
||||
|
// Configure Management layer to use EF Core.
|
||||
|
elsa.UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite())); |
||||
|
|
||||
|
// Configure Runtime layer to use EF Core.
|
||||
|
elsa.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite())); |
||||
|
|
||||
|
// Default Identity features for authentication/authorization.
|
||||
|
elsa.UseIdentity(identity => |
||||
|
{ |
||||
|
identity.TokenOptions = options => options.SigningKey = "sufficiently-large-secret-signing-key"; // This key needs to be at least 256 bits long.
|
||||
|
identity.UseAdminUserProvider(); |
||||
|
}); |
||||
|
|
||||
|
// Configure ASP.NET authentication/authorization.
|
||||
|
elsa.UseDefaultAuthentication(auth => auth.UseAdminApiKey()); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
// Register Razor services.
|
||||
|
context.Services.AddRazorPages(); |
||||
|
|
||||
|
context.Services.AddCoreInternal(); |
||||
|
context.Services.AddSharedServices(); |
||||
|
context.Services.AddTranslations(); |
||||
|
|
||||
|
context.Services.AddServerSideBlazor(options => |
||||
|
{ |
||||
|
// Register the root components.
|
||||
|
options.RootComponents.RegisterCustomElsaStudioElements(); |
||||
|
}); |
||||
|
// Register shell services and modules.
|
||||
|
var backendApiConfig = new BackendApiConfig |
||||
|
{ |
||||
|
ConfigureBackendOptions = options => configuration.GetSection("Backend").Bind(options), |
||||
|
ConfigureHttpClientBuilder = options => options.AuthenticationHandler = typeof(AuthenticatingApiHttpMessageHandler), |
||||
|
}; |
||||
|
context.Services.AddShell(options => configuration.GetSection("Shell").Bind(options)); |
||||
|
context.Services.AddRemoteBackend(backendApiConfig); |
||||
|
context.Services.AddLoginModule(); |
||||
|
context.Services.AddDashboardModule(); |
||||
|
context.Services.AddWorkflowsModule(); |
||||
|
context.Services.AddLocalizationModule(new LocalizationConfig |
||||
|
{ |
||||
|
ConfigureLocalizationOptions = options => configuration.GetSection("Localization").Bind(options), |
||||
|
}); |
||||
|
// Configure SignalR.
|
||||
|
context.Services.AddSignalR(options => |
||||
|
{ |
||||
|
// Set MaximumReceiveMessageSize to handle large workflows.
|
||||
|
options.MaximumReceiveMessageSize = 5 * 1024 * 1000; // 5MB
|
||||
|
}); |
||||
|
|
||||
|
// Add Health Checks.
|
||||
|
context.Services.AddHealthChecks(); |
||||
|
|
||||
|
|
||||
|
// Configure CORS to allow designer app hosted on a different origin to invoke the APIs.
|
||||
|
context.Services.AddCors(cors => cors |
||||
|
.AddDefaultPolicy(policy => policy |
||||
|
.AllowAnyOrigin() // For demo purposes only. Use a specific origin instead.
|
||||
|
.AllowAnyHeader() |
||||
|
.AllowAnyMethod() |
||||
|
.WithExposedHeaders("x-elsa-workflow-instance-id"))); |
||||
|
|
||||
|
// Swagger
|
||||
|
context.Services.AddSwaggerGen( |
||||
|
options => |
||||
|
{ |
||||
|
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Workflow API", Version = "v1" }); |
||||
|
options.DocInclusionPredicate((docName, description) => true); |
||||
|
options.CustomSchemaIds(type => type.FullName); |
||||
|
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
||||
|
{ |
||||
|
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", |
||||
|
Name = "Authorization", |
||||
|
In = ParameterLocation.Header, |
||||
|
Scheme = "bearer", |
||||
|
Type = SecuritySchemeType.Http, |
||||
|
BearerFormat = "JWT" |
||||
|
}); |
||||
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
||||
|
{ |
||||
|
{ |
||||
|
new OpenApiSecurityScheme |
||||
|
{ |
||||
|
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } |
||||
|
}, |
||||
|
new string[] { } |
||||
|
} |
||||
|
}); |
||||
|
options.OperationFilter<TenantHeaderParamter>(); |
||||
|
}); |
||||
|
|
||||
|
context.Services.AddTransient<AuthenticatingApiHttpMessageHandler>(); |
||||
|
context.Services.AddSingleton<IActivityFactory, AbpActivityFactory>(); |
||||
|
context.Services.AddScoped<ICultureService, AbpBlazorServerCultureService>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
{ |
||||
|
"DetailedErrors": true, |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Debug", |
||||
|
"Microsoft": "Debug" |
||||
|
} |
||||
|
}, |
||||
|
"Serilog": { |
||||
|
"MinimumLevel": { |
||||
|
"Default": "Information", |
||||
|
"Override": { |
||||
|
"Microsoft.AspNetCore.Routing": "Debug", |
||||
|
"System": "Information", |
||||
|
"Microsoft": "Information" |
||||
|
} |
||||
|
}, |
||||
|
"Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], |
||||
|
"WriteTo": [ |
||||
|
{ |
||||
|
"Name": "Console", |
||||
|
"Args": { |
||||
|
"initialMinimumLevel": "Verbose", |
||||
|
"standardErrorFromLevel": "Verbose", |
||||
|
"restrictedToMinimumLevel": "Verbose", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "Logs/Debug-.log", |
||||
|
"restrictedToMinimumLevel": "Debug", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "Logs/Info-.log", |
||||
|
"restrictedToMinimumLevel": "Information", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "Logs/Warn-.log", |
||||
|
"restrictedToMinimumLevel": "Warning", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "Logs/Error-.log", |
||||
|
"restrictedToMinimumLevel": "Error", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "Logs/Fatal-.log", |
||||
|
"restrictedToMinimumLevel": "Fatal", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
{ |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Information", |
||||
|
"Microsoft.AspNetCore": "Warning" |
||||
|
} |
||||
|
}, |
||||
|
"AllowedHosts": "*", |
||||
|
"Backend": { |
||||
|
"Url": "http://localhost:30036/elsa/api" |
||||
|
}, |
||||
|
"Hosting": { |
||||
|
"BaseUrl": "http://localhost:30036", |
||||
|
"BasePath": "/api/workflows" |
||||
|
}, |
||||
|
"Localization": { |
||||
|
"SupportedCultures": [ |
||||
|
"ar", |
||||
|
"de", |
||||
|
"fa", |
||||
|
"fr", |
||||
|
"nl", |
||||
|
"pt", |
||||
|
"uk", |
||||
|
"zh-Hans", |
||||
|
"zh-Hant" |
||||
|
] |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue