diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj index 76233328a..41f84616c 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj @@ -11,6 +11,7 @@ + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs index cac71425a..fc0630583 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Emailing; +using LINGYUN.Abp.WorkflowCore.Components.Authentication; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Emailing; using Volo.Abp.Modularity; using Volo.Abp.Sms; @@ -10,5 +12,9 @@ namespace LINGYUN.Abp.WorkflowCore.Components typeof(AbpWorkflowCoreModule))] public class AbpWorkflowCoreComponentsModule : AbpModule { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(AsyncLocalCurrentAssigner.Instance); + } } } diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/RemoteService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/RemoteService.cs new file mode 100644 index 000000000..e648318a5 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/RemoteService.cs @@ -0,0 +1,81 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace LINGYUN.Abp.WorkflowCore.Components.Primitives +{ + public class RemoteService : StepBodyAsyncBase + { + private readonly ICurrentTenant _currentTenant; + private readonly IServiceProvider _serviceProvider; + public RemoteService( + ICurrentTenant currentTenant, + IServiceProvider serviceProvider) + { + _currentTenant = currentTenant; + _serviceProvider = serviceProvider; + + Data = new Dictionary(); + } + /// + /// 远程服务接口类型 + /// + public string Interface { get; set; } + /// + /// 远程服务方法名称 + /// + public string Method { get; set; } + /// + /// 请求参数 + /// + public Dictionary Data { get; set; } + /// + /// 调用结果 + /// + public object Result { get; set; } + + public Guid? TenantId { get; set; } + public string CurrentCulture { get; set; } + + public override async Task RunAsync(IStepExecutionContext context) + { + var serviceType = Type.GetType(Interface, true, true); + var method = serviceType.GetMethod(Method); + + var serviceFactory = _serviceProvider.GetRequiredService(serviceType); + + using (_currentTenant.Change(TenantId)) + { + using (CultureHelper.Use(CurrentCulture ?? CultureInfo.CurrentCulture.Name)) + { + // TODO: 身份令牌? + // 工作流中是否需要调用API, 还是用户调用API之后传递事件激活下一个步骤 + + // Abp Api动态代理 + var result = (Task)method.Invoke(serviceFactory, Data.Select(x => x.Value).ToArray()); + await result; + + if (!method.ReturnType.GenericTypeArguments.IsNullOrEmpty()) + { + var resultType = method.ReturnType.GenericTypeArguments[0]; + var resultProperty = typeof(Task<>) + .MakeGenericType(resultType) + .GetProperty(nameof(Task.Result), BindingFlags.Instance | BindingFlags.Public); + + Result = resultProperty.GetValue(result); + } + + return ExecutionResult.Next(); + } + } + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/EmailStepBody.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs similarity index 85% rename from aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/EmailStepBody.cs rename to aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs index 1e737fd34..07e69b36a 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/EmailStepBody.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs @@ -12,21 +12,21 @@ using WorkflowCore.Models; namespace LINGYUN.Abp.WorkflowCore.Components.Primitives { - public class EmailStepBody : StepBodyAsyncBase + public class SendEmail : StepBodyAsyncBase { - public ILogger Logger { protected get; set; } + public ILogger Logger { protected get; set; } private readonly IEmailSender _emailSender; private readonly ITemplateRenderer _templateRenderer; - public EmailStepBody( + public SendEmail( IEmailSender emailSender, ITemplateRenderer templateRenderer) { _emailSender = emailSender; _templateRenderer = templateRenderer; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } [NotNull] diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SmsStepBody.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendSms.cs similarity index 81% rename from aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SmsStepBody.cs rename to aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendSms.cs index 4c10c3127..99613df63 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SmsStepBody.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendSms.cs @@ -9,18 +9,18 @@ using WorkflowCore.Models; namespace LINGYUN.Abp.WorkflowCore.Components.Primitives { - public class SmsStepBody : StepBodyAsyncBase + public class SendSms : StepBodyAsyncBase { - public ILogger Logger { protected get; set; } + public ILogger Logger { protected get; set; } private readonly ISmsSender _smsSender; - public SmsStepBody(ISmsSender smsSender) + public SendSms(ISmsSender smsSender) { _smsSender = smsSender; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } [NotNull] diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Elasticsearch/LINGYUN/Abp/WorkflowCore/Elasticsearch/AbpElasticsearchIndexer.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Elasticsearch/LINGYUN/Abp/WorkflowCore/Elasticsearch/AbpElasticsearchIndexer.cs index 81122060e..8023c8807 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Elasticsearch/LINGYUN/Abp/WorkflowCore/Elasticsearch/AbpElasticsearchIndexer.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Elasticsearch/LINGYUN/Abp/WorkflowCore/Elasticsearch/AbpElasticsearchIndexer.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using Volo.Abp; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.Search; @@ -46,7 +47,7 @@ namespace LINGYUN.Abp.WorkflowCore.Elasticsearch if (!result.ApiCall.Success) { _logger.LogError(default(EventId), result.ApiCall.OriginalException, $"Failed to index workflow {workflow.Id}"); - throw new ApplicationException($"Failed to index workflow {workflow.Id}", result.ApiCall.OriginalException); + throw new AbpException($"Failed to index workflow {workflow.Id}", result.ApiCall.OriginalException); } } diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.csproj new file mode 100644 index 000000000..f4dd0bf87 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.csproj @@ -0,0 +1,20 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchModule.cs new file mode 100644 index 000000000..da3bab3d4 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchModule.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch +{ + [DependsOn(typeof(AbpWorkflowCoreModule))] + public class AbpWorkflowCorePersistenceElasticsearchModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTransient(); + context.Services.AddTransient(); + + PreConfigure(options => + { + options.UsePersistence(provider => provider.GetRequiredService()); + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchOptions.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchOptions.cs new file mode 100644 index 000000000..4bf9dc672 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/AbpWorkflowCorePersistenceElasticsearchOptions.cs @@ -0,0 +1,14 @@ +namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch +{ + public class AbpWorkflowCorePersistenceElasticsearchOptions + { + /// + /// Default Value: abp.workflows.persistence + /// + public string IndexFormat { get; set; } + public AbpWorkflowCorePersistenceElasticsearchOptions() + { + IndexFormat = "abp.workflows.persistence"; + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/ElasticsearchPersistenceProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/ElasticsearchPersistenceProvider.cs new file mode 100644 index 000000000..93ca53e38 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/ElasticsearchPersistenceProvider.cs @@ -0,0 +1,555 @@ +using LINGYUN.Abp.Elasticsearch; +using LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Nest; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch +{ + public class ElasticsearchPersistenceProvider : IPersistenceProvider, ITransientDependency + { + private readonly ILogger _logger; + + private readonly IGuidGenerator _guidGenerator; + private readonly IElasticsearchClientFactory _elasticsearchClientFactory; + private readonly AbpWorkflowCorePersistenceElasticsearchOptions _options; + + public ElasticsearchPersistenceProvider( + IGuidGenerator guidGenerator, + IElasticsearchClientFactory elasticsearchClientFactory, + IOptions options, + ILogger logger) + { + _guidGenerator = guidGenerator; + _elasticsearchClientFactory = elasticsearchClientFactory; + _options = options.Value; + _logger = logger; + } + + public bool SupportsScheduledCommands => true; + + public virtual async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) + { + var id = Guid.Parse(eventSubscriptionId); + + var client = CreateClient(); + + var response = await client.GetAsync( + id, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + if (response.Found) + { + if (response.Source.ExternalToken != token) + { + throw new InvalidOperationException(); + } + response.Source.ExternalToken = null; + response.Source.ExternalWorkerId = null; + response.Source.ExternalTokenExpiry = null; + + await client.UpdateAsync( + id, + dsl => dsl.Index(CreateIndex()) + .Doc(response.Source), + ct: cancellationToken); + } + } + + public virtual async Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var newEventId = _guidGenerator.Create(); + + newEvent.Id = newEventId.ToString(); + + var response = await client.IndexAsync( + newEvent, + dsl => dsl.Index(CreateIndex()) + .Id(newEventId), + ct: cancellationToken); + + CheckResponse(response); + + return newEvent.Id; + } + + public virtual async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var newSubscriptionId = _guidGenerator.Create(); + + subscription.Id = newSubscriptionId.ToString(); + + var response = await client.IndexAsync( + subscription, + dsl => dsl.Index(CreateIndex()) + .Id(newSubscriptionId), + ct: cancellationToken); + + CheckResponse(response); + + return subscription.Id; + } + + public virtual async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var newWorkflowId = _guidGenerator.Create(); + + workflow.Id = newWorkflowId.ToString(); + + var response = await client.IndexAsync( + workflow, + dsl => dsl.Index(CreateIndex()) + .Id(newWorkflowId), + ct: cancellationToken); + + CheckResponse(response); + + return workflow.Id; + } + + public void EnsureStoreExists() + { + // TODO: 为什么是同步API... + var client = CreateClient(); + + var response = client.Indices.Exists(CreateIndex()); + if (!response.Exists) + { + client.Indices.Create(CreateIndex()); + } + } + + public virtual async Task GetEvent(string id, CancellationToken cancellationToken = default) + { + var eventId = Guid.Parse(id); + + var client = CreateClient(); + + var response = await client.GetAsync( + eventId, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + return response.Source; + } + + public virtual async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); + terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); + terms.Add(x => x.DateRange(t => t.Field(f => f.EventTime).GreaterThanOrEquals(asOf))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents.Select(x => x.Id); + } + + public virtual async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); + terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); + terms.Add(x => x.Term(t => t.Field(f => f.ExternalToken.Suffix("keyword")).Value(null))); + terms.Add(x => x.DateRange(t => t.Field(f => f.SubscribeAsOf).LessThanOrEquals(asOf))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))) + .Sort(s => s.Field(f => f.SubscribeAsOf, SortOrder.Ascending)) + .Take(1), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents.FirstOrDefault(); + } + + public virtual async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + var now = asAt.ToUniversalTime(); + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.Term(t => t.Field(f => f.IsProcessed).Value(false))); + terms.Add(x => x.DateRange(t => t.Field(f => f.EventTime).LessThanOrEquals(now))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents.Select(x => x.Id); + } + + public virtual async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + var now = asAt.ToUniversalTime().Ticks; + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.LongRange(t => t.Field(f => f.NextExecution).LessThanOrEquals(now))); + terms.Add(x => x.Term(t => t.Field(f => f.Status).Value(WorkflowStatus.Runnable))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents.Select(x => x.Id); + } + + public virtual async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var id = Guid.Parse(eventSubscriptionId); + + var response = await client.GetAsync( + id, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + return response.Source; + } + + public virtual async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + var now = asOf.ToUniversalTime(); + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); + terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); + terms.Add(x => x.DateRange(t => t.Field(f => f.SubscribeAsOf).LessThanOrEquals(now))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.IncludeAll()), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents; + } + + public virtual async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) + { + var workflowId = Guid.Parse(Id); + var client = CreateClient(); + + var response = await client.GetAsync( + workflowId, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + return response.Source; + } + + public virtual async Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) + { + var client = CreateClient(); + + var terms = new List, QueryContainer>>(); + + if (status.HasValue) + { + terms.Add(x => x.Term(t => t.Field(f => f.Status).Value(status.Value))); + } + if (!type.IsNullOrWhiteSpace()) + { + terms.Add(x => x.Term(t => t.Field(f => f.WorkflowDefinitionId.Suffix("keyword")).Value(type))); + } + if (createdFrom.HasValue) + { + terms.Add(x => x.DateRange(t => t.Field(f => f.CreateTime).GreaterThanOrEquals(createdFrom.Value))); + } + if (createdTo.HasValue) + { + terms.Add(x => x.DateRange(t => t.Field(f => f.CreateTime).LessThanOrEquals(createdTo.Value))); + } + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.IncludeAll()) + .Skip(skip) + .Take(take)); + + CheckResponse(response); + + return response.Documents; + } + + public virtual async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => + q.Bool(b => + b.Should(s => + s.Terms(t => t.Field(f => f.Id.Suffix("keyword")).Terms(ids))))) + .Source(s => s.IncludeAll()), + ct: cancellationToken); + + CheckResponse(response); + + return response.Documents; + } + + public virtual async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) + { + var eventId = Guid.Parse(id); + + var client = CreateClient(); + + var response = await client.GetAsync( + eventId, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + if (response.Found) + { + response.Source.IsProcessed = true; + + await client.UpdateAsync( + id, + dsl => dsl.Index(CreateIndex()) + .Doc(response.Source), + ct: cancellationToken); + } + } + + public virtual async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) + { + var eventId = Guid.Parse(id); + + var client = CreateClient(); + + var response = await client.GetAsync( + eventId, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + if (response.Found) + { + response.Source.IsProcessed = false; + + await client.UpdateAsync( + id, + dsl => dsl.Index(CreateIndex()) + .Doc(response.Source), + ct: cancellationToken); + } + } + + public virtual async Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default) + { + var executionErrors = errors as ExecutionError[] ?? errors.ToArray(); + if (executionErrors.Any()) + { + var client = CreateClient(); + + var response = await client.IndexManyAsync( + errors, + CreateIndex(), + cancellationToken: cancellationToken); + + CheckResponse(response); + } + } + + public virtual async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) + { + var workflowId = Guid.Parse(workflow.Id); + + var client = CreateClient(); + + var response = await client.GetAsync( + workflowId, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + await client.UpdateAsync( + workflowId, + dsl => dsl.Index(CreateIndex()) + .Doc(workflow), + ct: cancellationToken); + } + + public virtual async Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + var client = CreateClient(); + + var terms = new List, QueryContainer>>(); + + terms.Add(x => x.LongRange(t => t.Field(f => f.ExecuteTime).LessThan(asOf.Ticks))); + + var response = await client.SearchAsync( + dsl => dsl.Index(CreateIndex()) + .Query(q => q.Bool(b => b.Filter(terms))) + .Source(s => s.IncludeAll()), + ct: cancellationToken); + + CheckResponse(response); + + foreach (var command in response.Documents) + { + try + { + await action(command.ToScheduledCommand()); + + await client.DeleteAsync( + command.Id, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + } + catch (Exception) + { + //TODO: add logger + } + } + } + + public virtual async Task ScheduleCommand(ScheduledCommand command) + { + var persistedCommand = new PersistedScheduledCommand( + _guidGenerator.Create(), + command); + + var client = CreateClient(); + + var response = await client.IndexAsync( + persistedCommand, + dsl => dsl.Index(CreateIndex()).Id(persistedCommand.Id)); + + CheckResponse(response); + } + + public virtual async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) + { + var id = Guid.Parse(eventSubscriptionId); + + var client = CreateClient(); + + var response = await client.GetAsync( + id, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + + if (response.Found) + { + response.Source.ExternalToken = token; + response.Source.ExternalWorkerId = workerId; + response.Source.ExternalTokenExpiry = expiry; + + var uptResponse = await client.UpdateAsync( + id, + dsl => dsl.Index(CreateIndex()) + .Doc(response.Source), + ct: cancellationToken); + + return uptResponse.Result == Result.Updated; + } + + return false; + } + + public virtual async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) + { + var id = Guid.Parse(eventSubscriptionId); + + var client = CreateClient(); + + var response = await client.DeleteAsync( + id, + dsl => dsl.Index(CreateIndex()), + ct: cancellationToken); + + CheckResponse(response); + } + + private IElasticClient CreateClient() + { + return _elasticsearchClientFactory.Create(); + } + + private string CreateIndex() + { + return _options.IndexFormat; + } + + private void CheckResponse(IResponse response) + { + if (!response.ApiCall.Success) + { + _logger.LogError(default(EventId), response.ApiCall.OriginalException, $"ES Operation Failed"); + throw new AbpException($"ES Operation Failed", response.ApiCall.OriginalException); + } + + if (!response.IsValid) + { + _logger.LogWarning("ES Request Valid Error: {0}", response.DebugInformation); + throw new InvalidOperationException(response.DebugInformation, response.OriginalException); + } + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/Models/PersistedScheduledCommand.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/Models/PersistedScheduledCommand.cs new file mode 100644 index 000000000..cceb7e57b --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch/LINGYUN/Abp/WorkflowCore/Persistence/Elasticsearch/Models/PersistedScheduledCommand.cs @@ -0,0 +1,32 @@ +using System; +using WorkflowCore.Models; + +namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.Models +{ + public class PersistedScheduledCommand + { + public Guid Id { get; set; } + public string CommandName { get; set; } + public string Data { get; set; } + public long ExecuteTime { get; set; } + + public PersistedScheduledCommand() { } + + public PersistedScheduledCommand(Guid id, ScheduledCommand command) + { + Id = id; + CommandName = command.CommandName; + Data = command.Data; + ExecuteTime = command.ExecuteTime; + } + public ScheduledCommand ToScheduledCommand() + { + return new ScheduledCommand + { + CommandName = CommandName, + Data = Data, + ExecuteTime = ExecuteTime + }; + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs index 7ce178b52..f2a887a25 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs @@ -10,8 +10,8 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence { public override void PreConfigureServices(ServiceConfigurationContext context) { - context.Services.AddSingleton(); - context.Services.AddSingleton(); + context.Services.AddTransient(); + context.Services.AddTransient(); PreConfigure(options => { diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs index 7de63fb84..d9d89b885 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.Linq; using Volo.Abp.MultiTenancy; @@ -15,7 +14,7 @@ using WorkflowCore.Models; namespace LINGYUN.Abp.WorkflowCore.Persistence { - public class AbpWorkflowPersistenceProvider : IPersistenceProvider, IUnitOfWorkEnabled, ITransientDependency + public class AbpWorkflowPersistenceProvider : IPersistenceProvider, IUnitOfWorkEnabled { public ILogger Logger { protected get; set; } diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN.Abp.WorkflowCore.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN.Abp.WorkflowCore.csproj index c8fb66894..8c9185900 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN.Abp.WorkflowCore.csproj +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN.Abp.WorkflowCore.csproj @@ -12,7 +12,11 @@ - + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpDateTimeProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpDateTimeProvider.cs new file mode 100644 index 000000000..863c8b202 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpDateTimeProvider.cs @@ -0,0 +1,22 @@ +using System; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; +using WorkflowCore.Interface; + +namespace LINGYUN.Abp.WorkflowCore +{ + [Dependency(ReplaceServices = true)] + public class AbpDateTimeProvider : IDateTimeProvider + { + private readonly IClock _clock; + + public AbpDateTimeProvider(IClock clock) + { + _clock = clock; + } + + public DateTime Now => _clock.Now; + + public DateTime UtcNow => _clock.Now.ToUtcDateTime(); + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj new file mode 100644 index 000000000..a3fe983ac --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj @@ -0,0 +1,20 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissionDefinitionProvider.cs new file mode 100644 index 000000000..b50e751e7 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissionDefinitionProvider.cs @@ -0,0 +1,23 @@ +using LINGYUN.Abp.WorkflowManagement.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.WorkflowManagement.Authorization +{ + public class WorkflowManagementPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var group = context.AddGroup(WorkflowManagementPermissions.GroupName, L("Permission:WorkflowManagement")); + + group.AddPermission( + WorkflowManagementPermissions.ManageSettings, + L("Permission:ManageSettings")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissions.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissions.cs new file mode 100644 index 000000000..3e7a64511 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissions.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.WorkflowManagement.Authorization +{ + public static class WorkflowManagementPermissions + { + public const string GroupName = "WorkflowManagement"; + + public const string ManageSettings = GroupName + ".ManageSettings"; + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationContractsModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationContractsModule.cs new file mode 100644 index 000000000..2070e61eb --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationContractsModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Application; +using Volo.Abp.Authorization; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WorkflowManagement +{ + [DependsOn( + typeof(AbpAuthorizationModule), + typeof(AbpDddApplicationContractsModule), + typeof(WorkflowManagementDomainSharedModule))] + public class WorkflowManagementApplicationContractsModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementRemoteServiceConsts.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementRemoteServiceConsts.cs new file mode 100644 index 000000000..72f9b4e65 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/WorkflowManagementRemoteServiceConsts.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.WorkflowManagement +{ + public static class WorkflowManagementRemoteServiceConsts + { + public const string RemoteServiceName = "WorkflowManagement"; + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN.Abp.WorkflowManagement.Application.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN.Abp.WorkflowManagement.Application.csproj new file mode 100644 index 000000000..b608d551f --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN.Abp.WorkflowManagement.Application.csproj @@ -0,0 +1,20 @@ + + + + + + + net6.0 + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementAppServiceBase.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementAppServiceBase.cs new file mode 100644 index 000000000..b8e034c68 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementAppServiceBase.cs @@ -0,0 +1,14 @@ +using LINGYUN.Abp.WorkflowManagement.Localization; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.WorkflowManagement +{ + public abstract class WorkflowManagementAppServiceBase : ApplicationService + { + protected WorkflowManagementAppServiceBase() + { + LocalizationResource = typeof(WorkflowManagementResource); + ObjectMapperContext = typeof(WorkflowManagementApplicationModule); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs new file mode 100644 index 000000000..2bb35efe9 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs @@ -0,0 +1,11 @@ +using AutoMapper; + +namespace LINGYUN.Abp.WorkflowManagement +{ + public class WorkflowManagementApplicationMapperProfile : Profile + { + public WorkflowManagementApplicationMapperProfile() + { + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationModule.cs new file mode 100644 index 000000000..978dd4b75 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationModule.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Application; +using Volo.Abp.Authorization; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WorkflowManagement +{ + [DependsOn( + typeof(AbpAuthorizationModule), + typeof(AbpDddApplicationContractsModule), + typeof(WorkflowManagementDomainSharedModule))] + public class WorkflowManagementApplicationModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN.Abp.WorkflowManagement.Domain.Shared.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN.Abp.WorkflowManagement.Domain.Shared.csproj new file mode 100644 index 000000000..dc270957e --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN.Abp.WorkflowManagement.Domain.Shared.csproj @@ -0,0 +1,27 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/en.json b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/en.json new file mode 100644 index 000000000..d656102c6 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "texts": { + "Permission:WorkflowManagement": "WorkflowManagement", + "Permission:ManageSettings": "Manage Settings" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..c18804bb8 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "Permission:WorkflowManagement": "WorkflowManagement", + "Permission:ManageSettings": "管理设置" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/WorkflowManagementResource.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/WorkflowManagementResource.cs new file mode 100644 index 000000000..ab702d05a --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/WorkflowManagementResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.WorkflowManagement.Localization +{ + [LocalizationResourceName("WorkflowManagement")] + public class WorkflowManagementResource + { + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainSharedModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainSharedModule.cs new file mode 100644 index 000000000..e580439ba --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainSharedModule.cs @@ -0,0 +1,33 @@ +using LINGYUN.Abp.WorkflowManagement.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.WorkflowManagement +{ + [DependsOn( + typeof(AbpLocalizationModule))] + public class WorkflowManagementDomainSharedModule: AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add() + .AddVirtualJson("/Abp/WorkflowManagement/Localization/Resources"); + }); + + Configure(options => + { + options.MapCodeNamespace(WorkflowManagementErrorCodes.Namespace, typeof(WorkflowManagementResource)); + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementErrorCodes.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementErrorCodes.cs new file mode 100644 index 000000000..9d611e14e --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowManagementErrorCodes.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.WorkflowManagement +{ + public static class WorkflowManagementErrorCodes + { + public const string Namespace = "WorkflowManagement"; + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN.Abp.WorkflowManagement.Domain.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN.Abp.WorkflowManagement.Domain.csproj new file mode 100644 index 000000000..7a89be011 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN.Abp.WorkflowManagement.Domain.csproj @@ -0,0 +1,22 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettingDefinitionProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettingDefinitionProvider.cs new file mode 100644 index 000000000..75b00b4dc --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettingDefinitionProvider.cs @@ -0,0 +1,11 @@ +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.WorkflowManagement.Settings +{ + public class WorkflowManagementSettingDefinitionProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettings.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettings.cs new file mode 100644 index 000000000..6e390b586 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Settings/WorkflowManagementSettings.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.WorkflowManagement.Settings +{ + public static class WorkflowManagementSettings + { + public const string GroupName = "WorkflowManagement"; + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs new file mode 100644 index 000000000..3fc65ef3a --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs @@ -0,0 +1,57 @@ +using System; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; +using Volo.Abp.MultiTenancy; +using WorkflowCore.Models; + +namespace LINGYUN.Abp.WorkflowManagement +{ + public class Step : Entity, IMultiTenant + { + public virtual Guid? TenantId { get; protected set; } + public virtual Guid WorkflowId { get; protected set; } + public virtual string Name { get; protected set;} + public virtual string StepType { get; protected set; } + public virtual string CancelCondition { get; set; } + public virtual WorkflowErrorHandling? ErrorBehavior { get; protected set; } + public virtual int? RetryInterval { get; set; } + public virtual bool Saga { get; set; } + public virtual Guid? NextStep { get; protected set; } + public virtual ExtraPropertyDictionary Inputs { get; set; } + public virtual ExtraPropertyDictionary Outputs { get; set; } + public virtual ExtraPropertyDictionary SelectNextStep { get; set; } + protected Step() + { + Inputs = new ExtraPropertyDictionary(); + Outputs = new ExtraPropertyDictionary(); + SelectNextStep = new ExtraPropertyDictionary(); + } + + public Step( + Guid id, + Guid workflowId, + string name, + string stepType, + string cancelCondition, + WorkflowErrorHandling? errorBehavior = null, + int? retryInterval = null, + bool saga = false, + Guid? nextStep = null, + Guid? tenantId = null) : base(id) + { + Name = name; + WorkflowId = workflowId; + StepType = stepType; + CancelCondition = cancelCondition; + ErrorBehavior = errorBehavior; + RetryInterval = retryInterval; + Saga = saga; + NextStep = nextStep; + TenantId = tenantId; + + Inputs = new ExtraPropertyDictionary(); + Outputs = new ExtraPropertyDictionary(); + SelectNextStep = new ExtraPropertyDictionary(); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs new file mode 100644 index 000000000..abebeb49b --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs @@ -0,0 +1,45 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.WorkflowManagement +{ + /// + /// 流程定义 + /// + public class Workflow : AuditedAggregateRoot, IMultiTenant + { + /// + /// 租户标识 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 是否启用 + /// + public virtual bool IsEnabled { get; protected set; } + /// + /// 显示名称 + /// + public virtual string DisplayName { get; set; } + /// + /// 描述 + /// + public virtual string Description { get; set; } + /// + /// 版本号 + /// + public virtual int Version { get; protected set; } + + protected Workflow() + { + } + + public Workflow( + Guid id, + string displayName, + string description = "", + int version = 1) : base(id) + { + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs new file mode 100644 index 000000000..2f85c3451 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs @@ -0,0 +1,12 @@ +namespace LINGYUN.Abp.WorkflowManagement +{ + public static class WorkflowManagementDbProperties + { + public static string DbTablePrefix { get; set; } = "WorkflowManagement_"; + + public static string DbSchema { get; set; } = null; + + + public const string ConnectionStringName = "WorkflowManagement"; + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainMapperProfile.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainMapperProfile.cs new file mode 100644 index 000000000..611ba1f66 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainMapperProfile.cs @@ -0,0 +1,12 @@ +using AutoMapper; + +namespace LINGYUN.Abp.WorkflowManagement +{ + public class WorkflowManagementDomainMapperProfile: Profile + { + public WorkflowManagementDomainMapperProfile() + { + + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs new file mode 100644 index 000000000..9e3dede8e --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WorkflowManagement +{ + [DependsOn( + typeof(AbpAutoMapperModule), + typeof(WorkflowManagementDomainSharedModule))] + public class WorkflowManagementDomainModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + + Configure(options => + { + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore.csproj new file mode 100644 index 000000000..7f1addccf --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore.csproj @@ -0,0 +1,19 @@ + + + + + + + net6.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/IWorkflowManagementDbContext.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/IWorkflowManagementDbContext.cs new file mode 100644 index 000000000..8d3e0d604 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/IWorkflowManagementDbContext.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore +{ + [ConnectionStringName(WorkflowManagementDbProperties.ConnectionStringName)] + public interface IWorkflowManagementDbContext : IEfCoreDbContext + { + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContext.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContext.cs new file mode 100644 index 000000000..0dda1a31d --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContext.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore +{ + public class WorkflowManagementDbContext : AbpDbContext, IWorkflowManagementDbContext + { + public WorkflowManagementDbContext( + DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureWorkflowManagement(); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContextModelCreatingExtensions.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContextModelCreatingExtensions.cs new file mode 100644 index 000000000..7d88cc563 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContextModelCreatingExtensions.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; +using System; +using Volo.Abp; + +namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore +{ + public static class WorkflowManagementDbContextModelCreatingExtensions + { + public static void ConfigureWorkflowManagement( + this ModelBuilder builder, + Action optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new WorkflowManagementModelBuilderConfigurationOptions( + WorkflowManagementDbProperties.DbTablePrefix, + WorkflowManagementDbProperties.DbSchema + ); + optionsAction?.Invoke(options); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementEntityFrameworkCoreModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..424a5e701 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementEntityFrameworkCoreModule.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore +{ + [DependsOn( + typeof(WorkflowManagementDomainModule), + typeof(AbpEntityFrameworkCoreModule))] + public class WorkflowManagementEntityFrameworkCoreModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + options.AddDefaultRepositories(includeAllEntities: true); + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementModelBuilderConfigurationOptions.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementModelBuilderConfigurationOptions.cs new file mode 100644 index 000000000..b5cbe5216 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementModelBuilderConfigurationOptions.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore +{ + public class WorkflowManagementModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions + { + public WorkflowManagementModelBuilderConfigurationOptions( + [NotNull] string tablePrefix = "", + [CanBeNull] string schema = null) + : base( + tablePrefix, + schema) + { + + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN.Abp.WorkflowManagement.HttpApi.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN.Abp.WorkflowManagement.HttpApi.csproj new file mode 100644 index 000000000..74350395b --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN.Abp.WorkflowManagement.HttpApi.csproj @@ -0,0 +1,19 @@ + + + + + + + net6.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/WorkflowManagementHttpApiModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/WorkflowManagementHttpApiModule.cs new file mode 100644 index 000000000..b04915b6b --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/WorkflowManagementHttpApiModule.cs @@ -0,0 +1,41 @@ +using LINGYUN.Abp.WorkflowManagement.Localization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Validation.Localization; + +namespace LINGYUN.Abp.WorkflowManagement +{ + [DependsOn( + typeof(AbpAspNetCoreMvcModule), + typeof(WorkflowManagementApplicationContractsModule))] + public class WorkflowManagementHttpApiModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(WorkflowManagementHttpApiModule).Assembly); + }); + + PreConfigure(options => + { + options.AddAssemblyResource( + typeof(WorkflowManagementResource), + typeof(WorkflowManagementApplicationContractsModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes(typeof(AbpValidationResource)); + }); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN.Abp.WorkflowManagement.SettingManagement.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN.Abp.WorkflowManagement.SettingManagement.csproj new file mode 100644 index 000000000..7bc62e6dc --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN.Abp.WorkflowManagement.SettingManagement.csproj @@ -0,0 +1,20 @@ + + + + + + net5.0 + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingAppService.cs new file mode 100644 index 000000000..50aa31f04 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingAppService.cs @@ -0,0 +1,77 @@ +using LINGYUN.Abp.WorkflowManagement.Authorization; +using LINGYUN.Abp.WorkflowManagement.Localization; +using LINGYUN.Abp.SettingManagement; +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Features; +using Volo.Abp.MultiTenancy; +using Volo.Abp.SettingManagement; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.WorkflowManagement.SettingManagement +{ + [Authorize(WorkflowManagementPermissions.ManageSettings)] + public class SettingAppService : ApplicationService, ISettingAppService + { + protected ISettingManager SettingManager { get; } + protected ISettingDefinitionManager SettingDefinitionManager { get; } + + public SettingAppService( + ISettingManager settingManager, + ISettingDefinitionManager settingDefinitionManager) + { + SettingManager = settingManager; + SettingDefinitionManager = settingDefinitionManager; + LocalizationResource = typeof(WorkflowManagementResource); + } + + public virtual async Task> GetAllForCurrentTenantAsync() + { + return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); + } + + public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input) + { + // 增加特性检查 + await CheckFeatureAsync(); + + if (CurrentTenant.IsAvailable) + { + foreach (var setting in input.Settings) + { + await SettingManager.SetForTenantAsync(CurrentTenant.GetId(), setting.Name, setting.Value); + } + + await CurrentUnitOfWork.SaveChangesAsync(); + } + } + + protected virtual async Task CheckFeatureAsync() + { + await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable); + } + + protected virtual async Task> GetAllForProviderAsync(string providerName, string providerKey) + { + var settingGroups = new List(); + + await Task.CompletedTask; + + return new ListResultDto(settingGroups); + } + + public Task SetGlobalAsync(UpdateSettingsDto input) + { + throw new NotSupportedException(); + } + + public Task> GetAllForGlobalAsync() + { + throw new NotSupportedException(); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingController.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingController.cs new file mode 100644 index 000000000..ed7f05c8c --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/SettingController.cs @@ -0,0 +1,48 @@ +using LINGYUN.Abp.SettingManagement; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.WorkflowManagement.SettingManagement +{ + [RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)] + [ApiVersion("2.0")] + [Area("WorkflowManagement")] + [Route("api/WorkflowManagement/settings")] + public class SettingController : AbpController, ISettingAppService + { + private readonly ISettingAppService _settingAppService; + public SettingController(ISettingAppService settingAppService) + { + _settingAppService = settingAppService; + } + + [HttpPut] + public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input) + { + await _settingAppService.SetCurrentTenantAsync(input); + } + + [HttpGet] + public virtual async Task> GetAllForCurrentTenantAsync() + { + return await _settingAppService.GetAllForCurrentTenantAsync(); + } + + [HttpPost] + [Route("by-global")] + public virtual async Task SetGlobalAsync(UpdateSettingsDto input) + { + await _settingAppService.SetGlobalAsync(input); + } + + [HttpGet] + [Route("by-global")] + public virtual async Task> GetAllForGlobalAsync() + { + return await _settingAppService.GetAllForGlobalAsync(); + } + } +} diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/WorkflowManagementSettingManagementModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/WorkflowManagementSettingManagementModule.cs new file mode 100644 index 000000000..39af2fea0 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.SettingManagement/LINGYUN/Abp/WorkflowManagement/SettingManagement/WorkflowManagementSettingManagementModule.cs @@ -0,0 +1,15 @@ +using LINGYUN.Abp.SettingManagement; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Modularity; +using Volo.Abp.SettingManagement; + +namespace LINGYUN.Abp.WorkflowManagement.SettingManagement +{ + [DependsOn( + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpSettingManagementDomainModule))] + public class WorkflowManagementSettingManagementModule : AbpModule + { + } +}