diff --git a/src/apps/Caspian.WorkflowFramework.Sample/appsettings.json b/src/apps/Caspian.WorkflowFramework.Sample/appsettings.json index fcfb280..5c0bfc1 100644 --- a/src/apps/Caspian.WorkflowFramework.Sample/appsettings.json +++ b/src/apps/Caspian.WorkflowFramework.Sample/appsettings.json @@ -40,7 +40,7 @@ "ConnectionStrings": { //"DefaultConnection": "Data Source=.;Initial Catalog=WfDb;User ID=sa;Password=123456;Integrated Security=false;TrustServerCertificate=True;" //"DefaultConnection": "Server=.;Database=CaspianWfDb;User Id=sa;Password=123456;TrustServerCertificate=True;" - "DefaultConnection": "Server=.;Database=Workflow_Db;User Id=sa;Password=123456;TrustServerCertificate=True;" + "DefaultConnection": "Server=.;Database=WfLive;User Id=sa;Password=123456;TrustServerCertificate=True;" //"DefaultConnection": "Server=192.168.251.161;Database=Workflow_Db;User Id=sa;Password=cLL{3N29D@n2;MultipleActiveResultSets=true;TrustServerCertificate=True" } } diff --git a/src/apps/Caspian.WorkflowFramework/Models/PublishEventModel.cs b/src/apps/Caspian.WorkflowFramework/Models/PublishEventModel.cs index 479f132..e066806 100644 --- a/src/apps/Caspian.WorkflowFramework/Models/PublishEventModel.cs +++ b/src/apps/Caspian.WorkflowFramework/Models/PublishEventModel.cs @@ -19,4 +19,6 @@ public class PublishEventModel [Required] public JsonElement EventData { get; set; } + + public string? SessionId { get; set; } } diff --git a/src/apps/Caspian.WorkflowFramework/Services/WorkflowService.cs b/src/apps/Caspian.WorkflowFramework/Services/WorkflowService.cs index c4b8a32..bbab017 100644 --- a/src/apps/Caspian.WorkflowFramework/Services/WorkflowService.cs +++ b/src/apps/Caspian.WorkflowFramework/Services/WorkflowService.cs @@ -18,9 +18,11 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; using San.MongoLogger; namespace Caspian.WorkflowFramework.Services; + public class WorkflowService : IWorkflowService, ILoggable { #region Fields @@ -294,22 +296,34 @@ public class WorkflowService : IWorkflowService, ILoggable return response; } - dynamic payload = null; + ExpandoObject payload; - if (input.EventData.ValueKind != JsonValueKind.Undefined && - input.EventData.ValueKind != JsonValueKind.Null) + var payloadObject = new JObject(); + + if (input.EventData.ValueKind is not JsonValueKind.Undefined + and not JsonValueKind.Null) { - var json = input.EventData.GetRawText(); + if (input.EventData.ValueKind != JsonValueKind.Object) + throw new InvalidOperationException("EventData must be a JSON object."); - var settings = new JsonSerializerSettings - { - Converters = { new ExpandoObjectConverter() } - }; - - // تبدیل JSON به object داینامیک - payload = JsonConvert.DeserializeObject(json, settings); + payloadObject = JObject.Parse(input.EventData.GetRawText()); } + if (!string.IsNullOrWhiteSpace(input.SessionId)) + { + payloadObject["SessionId"] = input.SessionId; + } + + var settings = new JsonSerializerSettings + { + Converters = { new ExpandoObjectConverter() } + }; + + payload = JsonConvert.DeserializeObject( + payloadObject.ToString(Formatting.None), + settings + ) ?? new ExpandoObject(); + //await _eventPublisher.PublishAsync(input.EventName, null, input.WorkflowInstanceId, null, input.EventData, asynchronous: true); await _eventPublisher.PublishAsync(input.EventName, null, input.WorkflowInstanceId, null, payload); diff --git a/src/apps/Caspian.WorkflowFramework/Utility/ConversionExtensions.cs b/src/apps/Caspian.WorkflowFramework/Utility/ConversionExtensions.cs index ee0d3fa..e9ed87f 100644 --- a/src/apps/Caspian.WorkflowFramework/Utility/ConversionExtensions.cs +++ b/src/apps/Caspian.WorkflowFramework/Utility/ConversionExtensions.cs @@ -18,6 +18,9 @@ namespace Caspian.WorkflowFramework.Utility if (dictionary == null || dictionary.Count == 0) return workflowModel; + // قبل از تبدیل به مدل خروجی، sessionId حذف می‌شود. + dictionary.RemoveSessionId(); + //Map dictionary values to WorkflowModel properties workflowModel.InstanceId = dictionary.ContainsKey(nameof(workflowModel.InstanceId)) ? dictionary[nameof(workflowModel.InstanceId)]?.ToString() diff --git a/src/apps/Caspian.WorkflowFramework/Utility/WorkflowVariableExtensions.cs b/src/apps/Caspian.WorkflowFramework/Utility/WorkflowVariableExtensions.cs new file mode 100644 index 0000000..eb19fd4 --- /dev/null +++ b/src/apps/Caspian.WorkflowFramework/Utility/WorkflowVariableExtensions.cs @@ -0,0 +1,226 @@ +using System.Collections; +using System.Text.Json; +using System.Text.Json.Nodes; +using Newtonsoft.Json.Linq; + +namespace Caspian.WorkflowFramework.Utility; + +public static class WorkflowVariableExtensions +{ + private const string SessionIdKey = "SessionId"; + + /// + /// sessionId را از دیکشنری اصلی و تمام مقادیر تو در تو حذف می‌کند. + /// + public static Dictionary RemoveSessionId( + this Dictionary variables) + { + if (variables == null || variables.Count == 0) + return variables; + + RemoveSessionIdKeys(variables); + + foreach (var key in variables.Keys.ToList()) + variables[key] = RemoveSessionIdRecursive(variables[key]); + + return variables; + } + + private static object? RemoveSessionIdRecursive(object? value) + { + if (value == null) + return null; + + switch (value) + { + // Dictionary و ExpandoObject + case IDictionary dictionary: + { + RemoveSessionIdKeys(dictionary); + + foreach (var key in dictionary.Keys.ToList()) + dictionary[key] = RemoveSessionIdRecursive(dictionary[key]); + + return value; + } + + // System.Text.Json.Nodes + case JsonObject jsonObject: + { + RemoveSessionIdKeys(jsonObject); + + foreach (var property in jsonObject.ToList()) + jsonObject[property.Key] = + RemoveSessionIdFromJsonNode(property.Value); + + return jsonObject; + } + + case JsonArray jsonArray: + { + for (var i = 0; i < jsonArray.Count; i++) + { + jsonArray[i] = + RemoveSessionIdFromJsonNode(jsonArray[i]); + } + + return jsonArray; + } + + // JsonElement تغییرپذیر نیست؛ پس نسخه پاک‌سازی‌شده می‌سازیم. + case JsonElement jsonElement: + { + var node = JsonNode.Parse(jsonElement.GetRawText()); + + if (node == null) + return jsonElement; + + var cleanedNode = RemoveSessionIdFromJsonNode(node); + + return cleanedNode == null + ? jsonElement + : JsonSerializer.SerializeToElement(cleanedNode); + } + + // Newtonsoft.Json + case JObject jObject: + { + RemoveSessionIdKeys(jObject); + + foreach (var property in jObject.Properties().ToList()) + property.Value = RemoveSessionIdFromJToken(property.Value); + + return jObject; + } + + case JArray jArray: + { + for (var i = 0; i < jArray.Count; i++) + jArray[i] = RemoveSessionIdFromJToken(jArray[i]); + + return jArray; + } + + // سایر لیست‌ها و آرایه‌ها + case IList list: + { + for (var i = 0; i < list.Count; i++) + list[i] = RemoveSessionIdRecursive(list[i]); + + return list; + } + + case IEnumerable enumerable when value is not string: + { + foreach (var child in enumerable) + RemoveSessionIdRecursive(child); + + return value; + } + + default: + return value; + } + } + + private static JsonNode? RemoveSessionIdFromJsonNode(JsonNode? node) + { + if (node == null) + return null; + + switch (node) + { + case JsonObject jsonObject: + { + RemoveSessionIdKeys(jsonObject); + + foreach (var property in jsonObject.ToList()) + { + jsonObject[property.Key] = + RemoveSessionIdFromJsonNode(property.Value); + } + + break; + } + + case JsonArray jsonArray: + { + for (var i = 0; i < jsonArray.Count; i++) + { + jsonArray[i] = + RemoveSessionIdFromJsonNode(jsonArray[i]); + } + + break; + } + } + + return node; + } + + private static JToken RemoveSessionIdFromJToken(JToken token) + { + switch (token) + { + case JObject jObject: + { + RemoveSessionIdKeys(jObject); + + foreach (var property in jObject.Properties().ToList()) + property.Value = RemoveSessionIdFromJToken(property.Value); + + break; + } + + case JArray jArray: + { + for (var i = 0; i < jArray.Count; i++) + jArray[i] = RemoveSessionIdFromJToken(jArray[i]); + + break; + } + } + + return token; + } + + private static void RemoveSessionIdKeys( + IDictionary dictionary) + { + var keys = dictionary.Keys + .Where(IsSessionId) + .ToList(); + + foreach (var key in keys) + dictionary.Remove(key); + } + + private static void RemoveSessionIdKeys(JsonObject jsonObject) + { + var keys = jsonObject + .Select(x => x.Key) + .Where(IsSessionId) + .ToList(); + + foreach (var key in keys) + jsonObject.Remove(key); + } + + private static void RemoveSessionIdKeys(JObject jObject) + { + var properties = jObject.Properties() + .Where(x => IsSessionId(x.Name)) + .ToList(); + + foreach (var property in properties) + property.Remove(); + } + + private static bool IsSessionId(string key) + { + return string.Equals( + key, + SessionIdKey, + StringComparison.OrdinalIgnoreCase); + } +} \ No newline at end of file diff --git a/src/apps/Elsa.Server.Web/appsettings.json b/src/apps/Elsa.Server.Web/appsettings.json index 5598fa9..72f8e77 100644 --- a/src/apps/Elsa.Server.Web/appsettings.json +++ b/src/apps/Elsa.Server.Web/appsettings.json @@ -40,7 +40,7 @@ "Sqlite": "", //"Data Source=App_Data/elsa.sqlite.db;Cache=Shared;", //"SqlServer": "Server=localhost,1433;Initial Catalog=Elsa;User=sa;Password=!Elsa2025@;Encrypt=false;PersistSecurityInfo=false", //"SqlServer": "Server=.;Database=CaspianWfDb;User Id=sa;Password=123456;TrustServerCertificate=True;", - "SqlServer": "Server=.;Database=Workflow_Db;User Id=sa;Password=123456;TrustServerCertificate=True;", + "SqlServer": "Server=.;Database=WfLive;User Id=sa;Password=123456;TrustServerCertificate=True;", //"SqlServer": "Server=192.168.251.161;Database=Workflow_Db;User Id=sa;Password=cLL{3N29D@n2;MultipleActiveResultSets=true;TrustServerCertificate=True", "MySql": "", //"Server=localhost;Database=elsa;Uid=admin;Pwd=password;", "PostgreSql": "", //"Server=localhost;Username=elsa;Database=elsa;Port=5432;Password=elsa;SSLMode=Prefer;MaxPoolSize=2000;Timeout=60",