protected virtual bool CheckUsingSql(View view, Durados.Rule rule, Durados.TriggerDataAction dataAction, Dictionary <string, object> values, string pk, DataRow prevRow, string connectionString, int currentUserId, string currentUserRole) { using (IDbConnection connection = GetConnection(view)) { connection.Open(); string sql; if (dataAction == TriggerDataAction.BeforeCreate || dataAction == TriggerDataAction.AfterCreateBeforeCommit || dataAction == TriggerDataAction.AfterCreate || dataAction == TriggerDataAction.AfterDeleteBeforeCommit || dataAction == TriggerDataAction.AfterDelete) { sql = GetSql(rule, view, prevRow, null, currentUserId, currentUserRole, values); } else { sql = GetSql(rule, view, prevRow, pk, currentUserId, currentUserRole, values); } sql = sql.ReplaceWithDollar(view, values); sql = sql.ReplaceWithSharp(view, null, prevRow); if ((sql.Contains('$') || sql.Contains(Database.DictionaryPrefix + Database.SysPrevPlaceHolder)) && prevRow != null) { sql = sql.ReplaceWithDollar(view, values, prevRow); } if (sql.Contains('$') || sql.Contains('#') || sql.Contains(Database.DictionaryPrefix)) { return(false); } IDbCommand command = GetCommand(sql, connection); if (!string.IsNullOrEmpty(pk)) { foreach (SqlParameter parameter in GetWhereParemeters(view, pk)) { command.Parameters.Add(GetNewParameter(command, parameter.ParameterName, parameter.Value)); } } object scalar = null; try { scalar = command.ExecuteScalar(); } catch { return(false); } if (scalar == null || scalar == DBNull.Value) { return(false); } else { return(true); } } }
public virtual bool Check(Durados.TriggerDataAction dataAction, DataRow row) { if (row == null) { return(false); } List <Rule> rules = Rules.Values.Where(r => r.DataAction == dataAction).ToList(); int currentUserId = Convert.ToInt32(Database.GetUserID()); foreach (Durados.Rule rule in rules) { if ((new Durados.Workflow.LogicalParser()).Check(rule.WhereCondition.Replace(currentUserId).Replace(row))) { return(true); } } return(false); }
public virtual bool Check(View view, Durados.Rule rule, Durados.TriggerDataAction dataAction, Dictionary <string, object> values, string pk, DataRow prevRow, bool useSqlPareser, string connectionString, int currentUserId, string currentUserRole) { if (rule.WhereCondition.Equals("true")) { return(true); } if (useSqlPareser && view != view.Database.GetUserView()) { return(CheckUsingSql(view, rule, dataAction, values, pk, prevRow, connectionString, currentUserId, currentUserRole)); } else if (string.IsNullOrEmpty(rule.WhereCondition)) { return(true); } return(parser.Check(rule.WhereCondition.Replace(currentUserId) .Replace(Database.SysUsernamePlaceHolder.AsToken(), GetCurrentUsername(view)) .Replace(Database.SysRolePlaceHolder.AsToken(), currentUserRole) .Replace(GetPrevRowAsToken(view, prevRow)).Replace(GetValuesAsToken(values)).Replace(values) .ReplaceConfig(view))); //.ReplaceGlobals(view)); }
public bool ShouldTrigger(Durados.TriggerDataAction dataAction) { return(DataAction == dataAction || (DataAction == TriggerDataAction.AfterCreateOrEdit && (dataAction == TriggerDataAction.AfterCreate || dataAction == TriggerDataAction.AfterEdit))); }
public virtual void Execute(object controller, Dictionary <string, Parameter> parameters, View view, Dictionary <string, object> values, DataRow prevRow, string pk, string connectionString, int currentUsetId, string currentUserRole, IDbCommand command, IDbCommand sysCommand, string actionName, Durados.TriggerDataAction dataAction) { if (pk != null && (prevRow == null || dataAction == TriggerDataAction.AfterCreate || dataAction == TriggerDataAction.AfterEdit || dataAction == TriggerDataAction.AfterCreateBeforeCommit || dataAction == TriggerDataAction.AfterEditBeforeCommit) && controller is Durados.Data.IData) { try { if (((Durados.Data.IData)controller).DataHandler != null) { prevRow = ((Durados.Data.IData)controller).DataHandler.GetDataRow(view, pk, command); } } catch { } } var guid = Guid.NewGuid(); //if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Request.QueryString[GuidKey] != null) //{ // guid = new Guid(System.Web.HttpContext.Current.Request.QueryString[GuidKey]); //} SetCacheInCurrentRequest("js" + guid, new Dictionary <string, object>() { { "controller", controller }, { "connectionString", connectionString }, { "currentUsetId", currentUsetId }, { "currentUserRole", currentUserRole }, { "command", command }, { "sysCommand", sysCommand }, { "actionName", actionName }, { "dataAction", dataAction } }); SetCacheInCurrentRequest(ConnectionStringKey, view.Database.SysDbConnectionString); SetCacheInCurrentRequest(GuidKey, guid); if (!parameters.ContainsKey("code")) { throw new DuradosException("code was not supplied"); } string code = parameters["code"].Value.Replace(Engine.AsToken(values), ((Durados.Workflow.INotifier)controller).GetTableViewer(), view); string currentUsername = view.Database.GetCurrentUsername(); try { code = code.Replace(Durados.Database.UserPlaceHolder, currentUsetId.ToString(), false).Replace(Durados.Database.SysUserPlaceHolder.AsToken(), currentUsetId.ToString(), false) .Replace(Durados.Database.UsernamePlaceHolder, currentUsername, false).Replace(Durados.Database.SysUsernamePlaceHolder.AsToken(), currentUsername) .Replace(Durados.Database.RolePlaceHolder, currentUserRole, false).Replace(Durados.Database.SysRolePlaceHolder.AsToken(), currentUserRole) .ReplaceConfig(view); } catch { } Dictionary <string, object> clientParameters = new Dictionary <string, object>(); Dictionary <string, object> newRow = new Dictionary <string, object>(); Dictionary <string, object> oldRow = new Dictionary <string, object>(); Dictionary <string, object> userProfile = new Dictionary <string, object>(); bool debug = false; if (IsDebug()) { debug = true; } if (values != null) { foreach (string key in values.Keys) { if (key == "$$debug$$" || key == "$$debug$$".AsToken()) { debug = true; } else { string keyWithoutToken = key.TrimStart("{{".ToCharArray()).TrimEnd("}}".ToCharArray()); if (key.StartsWith("{{")) { if (!clientParameters.ContainsKey(keyWithoutToken)) { clientParameters.Add(keyWithoutToken, values[key]); } } if (view.GetFieldsByJsonName(keyWithoutToken) == null || view.GetFieldsByJsonName(keyWithoutToken).Length == 0) { if (view.Fields.ContainsKey(keyWithoutToken)) { string jsonName = view.Fields[keyWithoutToken].JsonName; if (!newRow.ContainsKey(jsonName)) { newRow.Add(jsonName, values[key]); } } else { if (!clientParameters.ContainsKey(keyWithoutToken)) { clientParameters.Add(keyWithoutToken, values[key]); } } } else { if (!newRow.ContainsKey(keyWithoutToken)) { newRow.Add(keyWithoutToken, values[key]); } } } } } SetCacheInCurrentRequest(Debug, debug); if (prevRow != null) { foreach (Field field in view.Fields.Values) { if (!oldRow.ContainsKey(field.JsonName)) { if (field.FieldType == FieldType.Column && field.IsDate) { oldRow.Add(field.JsonName, prevRow[((ColumnField)field).DataColumn.ColumnName]); } else { oldRow.Add(field.JsonName, field.GetValue(prevRow)); } } } //var shallowRow = view.RowToShallowDictionary(prevRow, pk); //foreach (Field field in view.Fields.Values) //{ // if (oldRow.ContainsKey(field.JsonName) && shallowRow.ContainsKey(field.JsonName)) // { // if (field.FieldType == FieldType.Column && (field.IsBoolean || field.IsPoint || field.IsNumeric)) // { // oldRow[field.JsonName] = shallowRow[field.JsonName]; // } // } //} } userProfile.Add("username", view.Database.GetCurrentUsername()); userProfile.Add("role", currentUserRole); userProfile.Add("app", view.Database.GetCurrentAppName()); userProfile.Add("userId", view.Database.GetCurrentUserId()); userProfile.Add("token", GetUserProfileAuthToken(view)); userProfile.Add("anonymousToken", view.Database.GetAnonymousToken().ToString()); userProfile.Add("info", GetUserProfileInfo(view)); if (!clientParameters.ContainsKey(FILEDATA)) { int parametersLimit = (int)view.Database.GetLimit(Limits.ActionParametersKbSize); HandleParametersSizeLimit(parametersLimit, clientParameters); userProfile.Add("request", GetRequest()); } var CONSTS = new Dictionary <string, object>() { { "apiUrl", System.Web.HttpContext.Current.Request.Url.Scheme + "://" + System.Web.HttpContext.Current.Request.Url.Host + ":" + System.Web.HttpContext.Current.Request.Url.Port + System.Web.HttpContext.Current.Request.ApplicationPath }, { "actionGuid", System.Web.HttpContext.Current.Request.QueryString[GuidKey] ?? (System.Web.HttpContext.Current.Items[GuidKey] ?? guid.ToString()) } }; //Newtonsoft.Json.JsonConvert.SerializeObject var theJavaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); theJavaScriptSerializer.MaxJsonLength = int.MaxValue; var parser = new Jint.Native.Json.JsonParser(call2); //var userInput = parser.Parse(theJavaScriptSerializer.Serialize(newRow)); //Object clientParametersToSend = null; //if (!clientParameters.ContainsKey("filedata")) //{ // clientParametersToSend = parser.Parse(theJavaScriptSerializer.Serialize(clientParameters)); //} //else //{ // System.Web.HttpContext.Current.Items["file_stream"] = clientParameters["filedata"]; // clientParameters["filedata"] = "file_stream"; // clientParametersToSend = clientParameters; //} //var dbRow = parser.Parse(theJavaScriptSerializer.Serialize(oldRow)); //var userProfile2 = parser.Parse(theJavaScriptSerializer.Serialize(userProfile)); //var CONSTS2 = parser.Parse(theJavaScriptSerializer.Serialize(CONSTS)); //var Config = view.Database.GetConfigDictionary(); //var Config2 = parser.Parse(theJavaScriptSerializer.Serialize(Config)); var userInput = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(newRow)); Object clientParametersToSend = null; bool upload = false; if (!clientParameters.ContainsKey(FILEDATA)) { clientParametersToSend = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(clientParameters)); } else { upload = true; System.Web.HttpContext.Current.Items["file_stream"] = clientParameters[FILEDATA]; clientParameters[FILEDATA] = "file_stream"; clientParametersToSend = clientParameters; } if (clientParameters.ContainsKey(FILEDATA) || clientParameters.ContainsKey(FILENAME)) { System.Web.HttpContext.Current.Items[StorageAccountsKey] = view.Database.CloudStorages; } var dbRow = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(oldRow)); var userProfile2 = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(userProfile)); var CONSTS2 = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(CONSTS)); var Config = view.Database.GetConfigDictionary(); var Config2 = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(Config)); var Environment = view.Database.GetEnvironmentDictionary(); var Environment2 = parser.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(Environment)); Limits limit = Limits.ActionTimeMSec; if (upload) { limit = Limits.UploadTimeMSec; } object actionTimeMSecObject = view.Database.GetLimit(limit); int actionTimeMSec = -1; if (!Int32.TryParse(actionTimeMSecObject.ToString(), out actionTimeMSec)) { throw new DuradosException("actionTimeMSecLimit in web.config is not numeric or too long"); } TimeSpan?timeoutInterval = new TimeSpan(0, 0, 0, 0, actionTimeMSec); if (actionTimeMSec == 0) { timeoutInterval = null; } string actionId = Guid.NewGuid().ToString(); string startMessage = theJavaScriptSerializer.Serialize(new { objectName = view.JsonName, actionName = actionName, id = actionId, @event = "started", time = GetSequence(view), data = new { userInput = newRow, dbRow = oldRow, parameters = clientParameters, userProfile = userProfile } }); Backand.Logger.Log(startMessage, 502); var call = new Jint.Engine(cfg => cfg.AllowClr(typeof(Backand.XMLHttpRequest).Assembly), timeoutInterval, GetLineStart(), new ActionPath() { @object = view.JsonName, action = actionName }); try { call.SetValue("userInput", userInput) .SetValue("btoa", new btoaHandler(Backand.Convert.btoa)) .SetValue("dbRow", dbRow) .SetValue("parameters", clientParametersToSend) .SetValue("userProfile", userProfile2) .SetValue("CONSTS", CONSTS2) .SetValue("Config", Config2) .SetValue("Environment", Environment2) .Execute(GetXhrWrapper() + code + "; function call(){return backandCallback(userInput, dbRow, parameters, userProfile);}"); } catch (TimeoutException exception) { Handle503(theJavaScriptSerializer, view.JsonName, actionName, actionId, exception.Message, view); string errorMessage = "Timeout: The operation took longer than " + actionTimeMSec + " milliseconds limit. at (" + view.JsonName + "/" + actionName + ")"; if (!IsSubAction()) { Backand.Logger.Log(exception.Message, 501); if (IsDebug()) { throw new MainActionInDebugJavaScriptException(errorMessage, exception); } else { throw new MainActionJavaScriptException(errorMessage, exception); } } else { throw new SubActionJavaScriptException(errorMessage, exception); } } catch (Exception exception) { Handle503(theJavaScriptSerializer, view.JsonName, actionName, actionId, exception.Message, view); string errorMessage = "Syntax error: " + HandleLineCodes(exception.Message, view.JsonName, actionName, view, IsDebug()); if (!IsSubAction()) { Backand.Logger.Log(exception.Message, 501); if (IsDebug()) { throw new MainActionInDebugJavaScriptException(errorMessage, exception); } else { throw new MainActionJavaScriptException(errorMessage, exception); } } else { throw new SubActionJavaScriptException(errorMessage, exception); } } object r = null; try { var r2 = call.GetValue("call").Invoke(); if (!r2.IsNull()) { r = r2.ToObject(); } string endMessage = null; try { endMessage = theJavaScriptSerializer.Serialize(new { objectName = view.JsonName, actionName = actionName, id = actionId, @event = "ended", time = GetSequence(view), data = r }); } catch (Exception exception) { if (exception.Message.StartsWith("A circular reference was detected while serializing an object")) { object oNull = null; endMessage = theJavaScriptSerializer.Serialize(new { objectName = view.JsonName, actionName = actionName, id = actionId, @event = "ended", time = GetSequence(view), data = oNull }); } else { endMessage = "Failed to serialize response"; if (!IsSubAction()) { Backand.Logger.Log(endMessage, 501); //if (IsDebug()) //{ // values[ReturnedValueKey] = message; // return; //} //else if (IsDebug()) { throw new MainActionInDebugJavaScriptException(endMessage, exception); } else { throw new MainActionJavaScriptException(endMessage, exception); } } else { throw new SubActionJavaScriptException(endMessage, exception); } } } Backand.Logger.Log(endMessage, 503); } catch (TimeoutException exception) { string message = "Timeout: The operation took longer than " + actionTimeMSec + " milliseconds limit. at (" + view.JsonName + "/" + actionName + ")"; Handle503(theJavaScriptSerializer, view.JsonName, actionName, actionId, message, view); if (!IsSubAction()) { Backand.Logger.Log(message, 501); if (IsDebug()) { throw new MainActionInDebugJavaScriptException(message, exception); } else { throw new MainActionJavaScriptException(message, exception); } } else { throw new SubActionJavaScriptException(message, exception); } } catch (Exception exception) { string message = (exception.InnerException == null) ? exception.Message : exception.InnerException.Message; string trace = message; if (exception is Jint.Runtime.JavaScriptException) { trace = ((Jint.Runtime.JavaScriptException)exception).GetTrace(); } trace = HandleLineCodes(trace, view.JsonName, actionName, view, IsDebug()); Handle503(theJavaScriptSerializer, view.JsonName, actionName, actionId, trace, view); if (!IsSubAction()) { IMainActionJavaScriptException mainActionJavaScriptException; Backand.Logger.Log(trace, 501); if (IsDebug()) { mainActionJavaScriptException = new MainActionInDebugJavaScriptException(message, exception); } else { mainActionJavaScriptException = new MainActionJavaScriptException(message, exception); } mainActionJavaScriptException.JintTrace = trace; throw (Exception)mainActionJavaScriptException; } else { throw new SubActionJavaScriptException(message, exception); } } var v = call.GetValue("userInput").ToObject(); if (v != null && v is System.Dynamic.ExpandoObject) { IDictionary <string, object> newValues = v as IDictionary <string, object>; foreach (string key in newValues.Keys) { if (values.ContainsKey(key)) { object val = newValues[key]; Field[] fields = view.GetFieldsByJsonName(key); val = DateConversion(view, val, fields); values[key] = val; } else { Field[] fields = view.GetFieldsByJsonName(key); if (fields.Length > 0) { string fieldName = fields[0].Name; object val = newValues[key]; val = DateConversion(view, val, fields); if (values.ContainsKey(fieldName)) { values[fieldName] = val; } else { values.Add(fieldName, val); } } else { values.Add(key, newValues[key]); } } } } if (r != null && values != null && dataAction == TriggerDataAction.OnDemand) { if (!values.ContainsKey(ReturnedValueKey)) { values.Add(ReturnedValueKey, r); } else { values[ReturnedValueKey] = r; } } }
protected virtual object ExecuteJs(object controller, Dictionary <string, Parameter> parameters, View view, DataRow prevRow, Dictionary <string, object> values, string pk, string connectionString, int currentUserId, string currentUserRole, IDbCommand command, IDbCommand sysCommand, string actionName, Durados.TriggerDataAction dataAction) { javaScript.Execute(controller, parameters, view, values, prevRow, pk, connectionString, currentUserId, currentUserRole, command, sysCommand, actionName, dataAction); return(null); }
protected virtual object PerformAction(object controller, Durados.WorkflowAction action, Dictionary <string, Parameter> parameters, View view, Dictionary <string, object> values, DataRow prevRow, string pk, string connectionString, int currentUserId, string currentUserRole, IDbCommand command, IDbCommand sysCommand, string actionName, Durados.TriggerDataAction dataAction, Rule rule) { switch (action) { case WorkflowAction.Notify: return(Notify(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command)); //case WorkflowAction.Task: // return Task(controller, parameters, view, values, pk, connectionString); case WorkflowAction.Validate: return(Validate(controller, parameters, view, values, prevRow, pk, connectionString, currentUserId, currentUserRole)); case WorkflowAction.Execute: return(Execute(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command)); case WorkflowAction.JavaScript: return(ExecuteJs(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command, sysCommand, actionName, dataAction)); case WorkflowAction.NodeJS: return(ExecuteNodeJS(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command, sysCommand, actionName)); case WorkflowAction.Lambda: return(ExecuteLambda(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command, sysCommand, actionName, rule)); case WorkflowAction.WebService: return(CallWebService(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command)); case WorkflowAction.CompleteStep: return(CompleteStep(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command)); case WorkflowAction.Approval: return(Approval(controller, parameters, view, prevRow, values, pk, connectionString, command)); case WorkflowAction.Document: return(Document(controller, parameters, view, prevRow, values, pk, connectionString, command)); case WorkflowAction.Xml: return(ExportToXml(controller, parameters, view, prevRow, values, pk, connectionString, currentUserId, currentUserRole, command)); case WorkflowAction.Custom: return(Custom(controller, parameters, values, pk, connectionString)); default: return(null); } }
public virtual void PerformActions(object controller, Durados.View view, Durados.TriggerDataAction dataAction, Dictionary <string, object> values, string pk, DataRow prevRow, string connectionString, int currentUserId, string currentUserRole, IDbCommand command, IDbCommand sysCommand, string ruleName = null) { SetCurrentDatabase(view); IEnumerable <Rule> rules = view.GetRules().Where(r => r.ShouldTrigger(dataAction)).OrderBy(r => r.Name).ToList(); if (ruleName != null) { rules = rules.Where(r => r.Name.Equals(ruleName)).ToList(); } List <Rule> failedRules = new List <Rule>(); List <Exception> exceptions = new List <Exception>(); Results = new Dictionary <string, object>(); foreach (Durados.Rule rule in rules) { bool isChecked = Check(view, rule, dataAction, values, pk, prevRow, rule.UseSqlParser, connectionString, currentUserId, currentUserRole); if (isChecked) { try { view.Database.Logger.Log(view.Name, "Start", "PerformAction " + rule.Name, "Engine", "", 14, view.Database.Logger.NowWithMilliseconds(), DateTime.Now); object result = PerformAction(controller, rule.WorkflowAction, rule.GetParameters(), view, values, prevRow, pk, connectionString, currentUserId, currentUserRole, command, sysCommand, rule.Name, dataAction, rule); view.Database.Logger.Log(view.Name, "End", "PerformAction " + rule.Name, "Engine", "", 14, view.Database.Logger.NowWithMilliseconds(), DateTime.Now); if (result != null) { Results.Add(rule.Name, result); if (result is Step.Result) { if (StepResult != null) { throw new WorkflowEngineException("Must be only one Complete Step rule"); } StepResult = (Step.Result)result; } } } catch (SqlExecuteException sqlExecuteException) { throw new WorkflowEngineException(sqlExecuteException.Message + "\nat (" + view.JsonName + "/" + rule.Name + ")"); } catch (WorkflowEngineException workflowEngineException) { if ((rule.Name == "Create My App User" || rule.Name == "Update My App User" || rule.Name == "Delete My App User") && !view.Database.Views.ContainsKey("users")) { } else { throw workflowEngineException; } } catch (Exception exception) { failedRules.Add(rule); exceptions.Add(exception); } } } if (exceptions.Count > 0) { if (exceptions[0] is NodeJsException && ((NodeJsException)exceptions[0]).JsonFormat) { throw exceptions[0]; } //Backand.Logger.Log(exceptions[0].Message + "\n" + exceptions[0].StackTrace, 501); if (IsDebug()) { throw new WorkflowEngineException(exceptions.ToArray(), failedRules.ToArray()); } else { throw exceptions[0]; } } }