public string wmGetMergedParameterXML(string sType, string sID, string sEcosystemID)
        {
            dataAccess dc = new dataAccess();
            acUI.acUI ui = new acUI.acUI();
            taskMethods tm = new taskMethods();
            FunctionTemplates.HTMLTemplates ft = new FunctionTemplates.HTMLTemplates();

            if (string.IsNullOrEmpty(sID))
                throw new Exception("ID required to look up default Parameter values.");

            string sErr = "";

            //what is the task associated with this action?
            //and get the XML for it
            string sSQL = "";
            string sDefaultsXML = "";
            string sTaskID = "";

            if (sType == "action")
            {
                sDefaultsXML = tm.wmGetObjectParameterXML(sType, sID, "");

                sSQL = "select t.task_id" +
                     " from ecotemplate_action ea" +
                     " join task t on ea.original_task_id = t.original_task_id" +
                     " and t.default_version = 1" +
                     " where ea.action_id = '" + sID + "'";
            }
            else if (sType == "instance")
            {
                sDefaultsXML = tm.wmGetObjectParameterXML(sType, sID, sEcosystemID);

                //IMPORTANT!!! if the ID is not a guid, it's a specific instance ID, and we'll need to get the task_id
                //but if it is a GUID, but the type is "instance", taht means the most recent INSTANCE for this TASK_ID
                if (ui.IsGUID(sID))
                    sTaskID = sID;
                else
                    sSQL = "select task_id" +
                         " from task_instance" +
                         " where task_instance = '" + sID + "'";
            }
            else if (sType == "plan")
            {
                sDefaultsXML = tm.wmGetObjectParameterXML(sType, sID, "");

                sSQL = "select task_id" +
                    " from action_plan" +
                    " where plan_id = '" + sID + "'";
            }
            else if (sType == "schedule")
            {
                sDefaultsXML = tm.wmGetObjectParameterXML(sType, sID, "");

                sSQL = "select task_id" +
                    " from action_schedule" +
                    " where schedule_id = '" + sID + "'";
            }

            //if we didn't get a task id directly, use the SQL to look it up
            if (string.IsNullOrEmpty(sTaskID))
                if (!dc.sqlGetSingleString(ref sTaskID, sSQL, ref sErr))
                    throw new Exception(sErr);

            if (!ui.IsGUID(sTaskID))
                throw new Exception("Unable to find Task ID for record.");

            XDocument xTPDoc = new XDocument();
            XDocument xDefDoc = new XDocument();

            //get the parameter XML from the TASK
            string sTaskParamXML = tm.wmGetParameterXML("task", sTaskID, "");
            if (!string.IsNullOrEmpty(sTaskParamXML))
            {
                xTPDoc = XDocument.Parse(sTaskParamXML);
                if (xTPDoc == null)
                    throw new Exception("Task Parameter XML data is invalid.");

                XElement xTPParams = xTPDoc.XPathSelectElement("/parameters");
                if (xTPParams == null)
                    throw new Exception("Task Parameter XML data does not contain 'parameters' root node.");
            }

            //we populated this up above too
            if (!string.IsNullOrEmpty(sDefaultsXML))
            {
                xDefDoc = XDocument.Parse(sDefaultsXML);
                if (xDefDoc == null)
                    throw new Exception("Defaults XML data is invalid.");

                XElement xDefParams = xDefDoc.XPathSelectElement("/parameters");
                if (xDefParams == null)
                    throw new Exception("Defaults XML data does not contain 'parameters' root node.");
            }

            //spin the nodes in the DEFAULTS xml, then dig in to the task XML and UPDATE the value if found.
            //(if the node no longer exists, delete the node from the defaults xml IF IT WAS AN ACTION)
            //and default "values" take precedence over task values.
            foreach (XElement xDefault in xDefDoc.XPathSelectElements("//parameter"))
            {
                //nothing to do if it's empty
                if (xDefault == null)
                    break;

                //look it up in the task param xml
                XElement xDefName = xDefault.XPathSelectElement("name");
                string sDefName = (xDefName == null ? "" : xDefName.Value);
                XElement xDefValues = xDefault.XPathSelectElement("values");

                //nothing to do if there is no values node...
                if (xDefValues == null)
                    break;
                //or if it contains no values.
                if (!xDefValues.HasElements)
                    break;
                //or if there is no parameter name
                if (string.IsNullOrEmpty(sDefName))
                    break;

                //so, we have some valid data in the defaults xml... let's merge!

                //we have the name of the parameter... go find it in the TASK param XML
                XElement xTaskParam = xTPDoc.XPathSelectElement("//parameter/name[. = '" + sDefName + "']/..");  //NOTE! the /.. gets the parent of the name node!

                //if it doesn't exist in the task params, remove it from this document, permanently
                //but only for action types... instance data is historical and can't be munged
                if (xTaskParam == null && sType == "action")
                {
                    ft.RemoveNodeFromXMLColumn("ecotemplate_action", "parameter_defaults", "action_id = '" + sID + "'", "//parameter/name[. = '" + sDefName + "']/..");
                    continue;
                }

                //is this an encrypted parameter?
                string sEncrypt = "";
                if (xTaskParam.Attribute("encrypt") != null)
                    sEncrypt = xTaskParam.Attribute("encrypt").Value;

                //and the "values" collection will be the 'next' node
                XElement xTaskParamValues = xTaskParam.XPathSelectElement("values");

                string sPresentAs = xTaskParamValues.Attribute("present_as").Value;
                if (sPresentAs == "dropdown")
                {
                    //dropdowns get a "selected" indicator
                    string sValueToSelect = xDefValues.XPathSelectElement("value").Value;

                    //find the right one by value and give it the "selected" attribute.
                    XElement xVal = xTaskParamValues.XPathSelectElement("value[. = '" + sValueToSelect + "']");
                    if (xVal != null)
                        xVal.SetAttributeValue("selected", "true");
                }
                else if (sPresentAs == "list")
                {
                    //first, a list gets ALL the values replaced...
                    xTaskParamValues.ReplaceNodes(xDefValues);
               	}
                else
                {
                    //IMPORTANT NOTE:
                    //remember... both these XML documents came from wmGetObjectParameterXML...
                    //so any encrypted data IS ALREADY OBFUSCATED and base64'd in the oev attribute.

                    //it's a single value, so just replace it with the default.
                    XElement xVal = xTaskParamValues.XPathSelectElement("value[1]");
                    if (xVal != null)
                    {
                        //if this is an encrypted parameter, we'll be replacing (if a default exists) the oev attribute
                        //AND the value... don't want them to get out of sync!
                        if (dc.IsTrue(sEncrypt))
                        {
                            if (xDefValues.XPathSelectElement("value") != null)
                                if (xDefValues.XPathSelectElement("value").Attribute("oev") != null)
                                {
                                    xVal.SetAttributeValue("oev", xDefValues.XPathSelectElement("value").Attribute("oev").Value);
                                    xVal.Value = xDefValues.XPathSelectElement("value").Value;
                                }
                        }
                        else
                        {
                            //not encrypted, just replace the value.
                            if (xDefValues.XPathSelectElement("value") != null)
                                xVal.Value = xDefValues.XPathSelectElement("value").Value;
                        }
                    }
                }
            }

            return xTPDoc.ToString(SaveOptions.DisableFormatting); ;
        }
Example #2
0
        public void wmSaveActionParameterXML(string sActionID, string sActionDefaultsXML)
        {
            dataAccess dc = new dataAccess();

            acUI.acUI ui = new acUI.acUI();
            taskMethods tm = new taskMethods();

            try
            {
                string sUserID = ui.GetSessionUserID();

                if (ui.IsGUID(sActionID) && ui.IsGUID(sUserID))
                {
                    string sErr = "";
                    string sSQL = "";

                    //we encoded this in javascript before the ajax call.
                    //the safest way to unencode it is to use the same javascript lib.
                    //(sometimes the javascript and .net libs don't translate exactly, google it.)
                    sActionDefaultsXML = ui.unpackJSON(sActionDefaultsXML);

                    //we gotta peek into the XML and encrypt any newly keyed values
                    PrepareAndEncryptParameterXML(ref sActionDefaultsXML);

                    //so, like when we read it, we gotta spin and compare, and build an XML that only represents *changes*
                    //to the defaults on the task.

                    //what is the task associated with this action?
                    sSQL = "select t.task_id" +
                        " from ecotemplate_action ea" +
                        " join task t on ea.original_task_id = t.original_task_id" +
                        " and t.default_version = 1" +
                        " where ea.action_id = '" + sActionID + "'";

                    string sTaskID = "";
                    if (!dc.sqlGetSingleString(ref sTaskID, sSQL, ref sErr))
                        throw new Exception(sErr);

                    if (!ui.IsGUID(sTaskID))
                        throw new Exception("Unable to find Task ID for Action.");

                    string sOverrideXML = "";
                    XDocument xTPDoc = new XDocument();
                    XDocument xADDoc = new XDocument();

                    //get the parameter XML from the TASK
                    string sTaskParamXML = tm.wmGetParameterXML("task", sTaskID, "");
                    if (!string.IsNullOrEmpty(sTaskParamXML))
                    {
                        xTPDoc = XDocument.Parse(sTaskParamXML);
                        if (xTPDoc == null)
                            throw new Exception("Task Parameter XML data is invalid.");

                        XElement xTPParams = xTPDoc.XPathSelectElement("/parameters");
                        if (xTPParams == null)
                            throw new Exception("Task Parameter XML data does not contain 'parameters' root node.");
                    }

                    //we had the ACTION defaults handed to us
                    if (!string.IsNullOrEmpty(sActionDefaultsXML))
                    {
                        xADDoc = XDocument.Parse(sActionDefaultsXML);
                        if (xADDoc == null)
                            throw new Exception("Action Defaults XML data is invalid.");

                        XElement xADParams = xADDoc.XPathSelectElement("/parameters");
                        if (xADParams == null)
                            throw new Exception("Action Defaults XML data does not contain 'parameters' root node.");
                    }

                    //spin the nodes in the ACTION xml, then dig in to the task XML and UPDATE the value if found.
                    //(if the node no longer exists, delete the node from the action XML)
                    //and action "values" take precedence over task values.

                    //this does a regular loop because we can't remove from an IEnumerable
                    int x = xADDoc.XPathSelectElements("//parameter").Count();
                    for (int i = (x-1); i>=0; i--)
                    {
                        XElement xDefault = xADDoc.XPathSelectElements("//parameter").ElementAt(i);

                        //look it up in the task param xml
                        XElement xADName = xDefault.XPathSelectElement("name");
                        string sADName = (xADName == null ? "" : xADName.Value);
                        XElement xADValues = xDefault.XPathSelectElement("values");
                        //string sValues = (xValues == null ? "" : xValues.ToString());

                        //now we have the name of the parameter, go find it in the TASK param XML
                        XElement xTaskParam = xTPDoc.XPathSelectElement("//parameter/name[. = '" + sADName + "']/..");  //NOTE! the /.. gets the parent of the name node!

                        //if it doesn't exist in the task params, remove it from this document
                        if (xTaskParam == null)
                        {
                            xDefault.Remove();
                            continue;
                        }

                        //and the "values" collection will be the 'next' node
                        XElement xTaskParamValues = xTaskParam.XPathSelectElement("values");

                        //so... it might be
                        //a) just an oev (original encrypted value) so de-base64 it
                        //b) a value flagged for encryption

                        //note we don't care about dirty unencrypted values... they'll compare down below just fine.

                        //is it encrypted?
                        bool bEncrypted = false;
                        if (xTaskParam.Attribute("encrypt") != null)
                            bEncrypted = dc.IsTrue(xTaskParam.Attribute("encrypt").Value);

                        if (bEncrypted)
                        {
                            foreach (XElement xVal in xADValues.XPathSelectElements("value"))
                            {
                                if (xVal.HasAttributes) {
                                    //a) is it an oev?  unpackJSON it (that's just an obfuscation wrapper)
                                    if (xVal.Attribute("oev") != null)
                                    {
                                        if (dc.IsTrue(xVal.Attribute("oev").Value))
                                        {
                                            xVal.Value = ui.unpackJSON(xVal.Value);
                                            xVal.SetAttributeValue("oev", null);
                                        }
                                    }

                                    //b) is it do_encrypt?  (remove the attribute to keep the db clutter down)
                                    if (xVal.Attribute("do_encrypt") != null)
                                    {
                                        xVal.Value = dc.EnCrypt(xVal.Value);
                                        xVal.SetAttributeValue("do_encrypt", null);
                                    }
                                }
                            }
                        }

                        //now that the encryption is sorted out,
                        // if the combined values of the parameter happens to match what's on the task
                        //  we just remove it.

                        //we're doing combined because of lists (the whole list must match for it to be a dupe)

                        //it's easy to look at all the values in a node with the node.Value property.
                        //but we'll have to manually concatenate all the oev attributes

                        string sTaskVals = "";
                        string sDefVals = "";

                        if (bEncrypted)
                        {
                            // the task document already has the oev obfuscated
                            foreach (XAttribute xa in xTaskParamValues.Elements("value").Attributes("oev"))
                            {
                                sTaskVals += xa.Value;
                            }
                            //but the XML we just got from the client doesn't... it's in the value.
                            foreach (XElement xe in xADValues.Elements("value"))
                            {
                                sDefVals += ui.packJSON(xe.Value);
                            }
                            if (sTaskVals.Equals(sDefVals))
                            {
                                xDefault.Remove();
                                continue;
                            }
                        }
                        else
                        {
                            if (xTaskParamValues.Value.Equals(xADValues.Value))
                            {
                                xDefault.Remove();
                                continue;
                            }
                        }

                    }

                    //done
                    sOverrideXML = xADDoc.ToString(SaveOptions.DisableFormatting);

                    //FINALLY, we have an XML that represents only the differences we wanna save.
                    sSQL = "update ecotemplate_action set" +
                        " parameter_defaults = '" + sOverrideXML + "'" +
                        " where action_id = '" + sActionID + "'";

                    if (!dc.sqlExecuteUpdate(sSQL, ref sErr))
                        throw new Exception("Unable to update Eco Template Action [" + sActionID + "]." + sErr);

                    ui.WriteObjectChangeLog(Globals.acObjectTypes.EcoTemplate, sActionID, sActionID, "Action default parameters updated: [" + sOverrideXML + "]");
                }
                else
                {
                    throw new Exception("Unable to update Eco Template Action. Missing or invalid Action ID.");
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return;
        }