public HttpResponseMessage Canvas(String tenantId, String flowId, String playerUrl)
        {
            String              redirectUrl   = null;
            String              signedRequest = null;
            CanvasRequest       canvasRequest = null;
            HttpResponseMessage response      = null;

            try
            {
                // Get the signed request from the form post
                signedRequest = System.Web.HttpContext.Current.Request.Form["signed_request"];

                // Grab the canvas request object from the post
                // The secret needs to be stored somewhere - actually, it doesn't - we don't need the secret at all
                canvasRequest = SalesforceCanvasUtils.VerifyAndDecode(null, signedRequest, "6156156167154975556");

                if (flowId == null ||
                    flowId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A flow identifier is required.  Please pass in a parameter for \"flow-id\".");
                }

                if (tenantId == null ||
                    tenantId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A tenant identifier is required.  Please pass in a parameter for \"tenant-id\".");
                }

                if (playerUrl == null ||
                    playerUrl.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A player is required.  Please pass in a parameter for \"player-url\".");
                }

                // Construct the redirect url so the player knows what to do
                redirectUrl  = "";
                redirectUrl += SettingUtils.GetStringSetting(SETTING_SERVER_BASE_PATH) + "/" + tenantId + "/play/" + playerUrl;
                redirectUrl += "?session-token=" + canvasRequest.client.oauthToken;
                redirectUrl += "&session-url=" + HttpUtility.HtmlEncode(canvasRequest.client.instanceUrl + canvasRequest.context.links.partnerUrl);

                // Create the run url stuff using utils
                redirectUrl = RunUtils.CompleteRunUrl(redirectUrl, Guid.Parse(flowId));

                // Tell the caller to redirect back to the desired location
                response = Request.CreateResponse(HttpStatusCode.RedirectMethod, redirectUrl);
                response.Headers.Add("Location", redirectUrl);
            }
            catch (Exception exception)
            {
                throw BaseHttpUtils.GetWebException(HttpStatusCode.BadRequest, BaseHttpUtils.GetExceptionMessage(exception));
            }

            return(response);
        }
        public HttpResponseMessage SessionSignIn(String tenantId, String flowId, String playerUrl, String sessionId, String sessionUrl)
        {
            String redirectUrl           = null;
            HttpResponseMessage response = null;

            try
            {
                if (flowId == null ||
                    flowId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A flow identifier is required.  Please pass in a parameter for \"flow-id\".");
                }

                if (tenantId == null ||
                    tenantId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A tenant identifier is required.  Please pass in a parameter for \"tenant-id\".");
                }

                if (playerUrl == null ||
                    playerUrl.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A player is required.  Please pass in a parameter for \"player-url\".");
                }

                // Construct the redirect url so the player knows what to do
                redirectUrl  = "";
                redirectUrl += SettingUtils.GetStringSetting(SETTING_SERVER_BASE_PATH) + "/" + tenantId + "/play/" + playerUrl;
                redirectUrl += "?session-token=" + sessionId;
                redirectUrl += "&session-url=" + sessionUrl;

                // Create the run url stuff using utils
                redirectUrl = RunUtils.CompleteRunUrl(redirectUrl, Guid.Parse(flowId));

                // Tell the caller to redirect back to the desired location
                response = Request.CreateResponse(HttpStatusCode.RedirectMethod, redirectUrl);
                response.Headers.Add("Location", redirectUrl);
            }
            catch (Exception exception)
            {
                throw BaseHttpUtils.GetWebException(HttpStatusCode.BadRequest, BaseHttpUtils.GetExceptionMessage(exception));
            }

            return(response);
        }
        /// <summary>
        /// This is a utility method for translating chatter messages into a compatible format for ManyWho.
        /// </summary>
        public MessageAPI ChatterMessageToMessageAPI(String chatterBaseUrl, String parentId, ChatterMessage chatterMessage)
        {
            MessageAPI    message    = null;
            AttachmentAPI attachment = null;

            message = new MessageAPI();

            if (chatterMessage.Attachment != null)
            {
                attachment         = new AttachmentAPI();
                attachment.name    = chatterMessage.Attachment.Title;
                attachment.iconUrl = string.Format("{0}{1}",
                                                   SettingUtils.GetStringSetting("ManyWho.CDNBasePath"),
                                                   SalesforceServiceSingleton.CHATTER_DEFAULT_FILE_IMAGE_URL);
                attachment.description = chatterMessage.Attachment.Description;
                attachment.type        = chatterMessage.Attachment.FileType;
                attachment.size        = chatterMessage.Attachment.FileSize;
                attachment.downloadUrl = chatterMessage.Attachment.DownloadUrl;

                // We need to scrub the download url as this url is the REST API that does not work through the browser
                if (string.IsNullOrWhiteSpace(chatterMessage.Attachment.DownloadUrl) == false &&
                    chatterMessage.Attachment.DownloadUrl.IndexOf("servlet.shepherd", StringComparison.OrdinalIgnoreCase) < 0 &&
                    chatterMessage.Attachment.DownloadUrl.IndexOf("/services/data/v", StringComparison.OrdinalIgnoreCase) >= 0 &&
                    chatterMessage.Attachment.DownloadUrl.IndexOf("/chatter/files", StringComparison.OrdinalIgnoreCase) > 0)
                {
                    String[] urlParts = chatterMessage.Attachment.DownloadUrl.Split('/');

                    // Check to make absolutely sure we have enough parts before adapting the url
                    if (chatterMessage.Attachment.DownloadUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase) == true &&
                        urlParts.Length >= 8)
                    {
                        // E.g. https://c.cs80.visual.force.com/services/data/v27.0/chatter/files/069250000000ixwAAA/content?versionNumber=1
                        // Get the file identifier, and make sure it's pointing to the correct instance
                        attachment.downloadUrl = chatterBaseUrl + "/" + urlParts[8];
                    }
                    else if (chatterMessage.Attachment.DownloadUrl.StartsWith("/services/data", StringComparison.OrdinalIgnoreCase) == true &&
                             urlParts.Length >= 6)
                    {
                        // E.g. /services/data/v27.0/chatter/files/069250000000jBeAAI/content?versionNumber=1
                        // We don't have the full url, so we need to adapt a smaller part
                        attachment.downloadUrl = chatterBaseUrl + "/" + urlParts[6];
                    }
                }

                message.attachments = new List <AttachmentAPI>();
                message.attachments.Add(attachment);
            }

            message.id          = chatterMessage.Id;
            message.repliedToId = null;

            if (chatterMessage.Comments != null)
            {
                message.commentsCount = chatterMessage.Comments.Total;

                if (chatterMessage.Comments.Comments != null &&
                    chatterMessage.Comments.Comments.Count > 0)
                {
                    // Convert the child messages over for this message
                    message.comments = this.ChatterMessageToMessageAPI(chatterBaseUrl, message.id, chatterMessage.Comments.Comments);
                }
            }

            if (chatterMessage.MyLike != null)
            {
                message.myLikeId = chatterMessage.MyLike.Id;
            }

            message.createdDate = DateTime.Parse(chatterMessage.CreatedDate);
            message.comments    = null;

            if (chatterMessage.Likes != null &&
                chatterMessage.Likes.Likes != null &&
                chatterMessage.Likes.Likes.Count > 0)
            {
                message.likerIds = new List <String>();

                foreach (ChatterLikeItem chatterLikeItem in chatterMessage.Likes.Likes)
                {
                    if (chatterLikeItem.User != null)
                    {
                        message.likerIds.Add(chatterLikeItem.User.Id);
                    }
                }
            }

            // The actor will be non-null for root posts, but it's the user for comments
            if (chatterMessage.Actor != null)
            {
                message.sender = this.ChatterUserInfoToWhoAPI(chatterMessage.Actor);
            }
            else
            {
                message.sender = this.ChatterUserInfoToWhoAPI(chatterMessage.User);
            }

            message.text = this.GetMessageText(chatterMessage);

            return(message);
        }
        public void SendEmail(List <EngineValueAPI> configurationValues, String fromEmail, String[] toEmails, String[] bccEmails, String subject, String textBody, String htmlBody, String token, String redirectUri, List <OutcomeAvailableAPI> outcomes)
        {
            NetworkCredential credentials   = null;
            SmtpClient        smtpClient    = null;
            MailMessage       mailMsg       = null;
            String            fullHtmlBody  = null;
            String            defaultEmail  = null;
            String            emailUsername = null;
            String            emailPassword = null;
            String            emailSmtp     = null;

            // Get the configuration information for the email
            defaultEmail  = ValueUtils.GetContentValue(ManyWhoUtilsSingleton.APP_SETTING_DEFAULT_FROM_EMAIL, configurationValues, true);
            emailUsername = ValueUtils.GetContentValue(ManyWhoUtilsSingleton.APP_SETTING_EMAIL_ACCOUNT_USERNAME, configurationValues, true);
            emailPassword = ValueUtils.GetContentValue(ManyWhoUtilsSingleton.APP_SETTING_EMAIL_ACCOUNT_PASSWORD, configurationValues, true);
            emailSmtp     = ValueUtils.GetContentValue(ManyWhoUtilsSingleton.APP_SETTING_EMAIL_ACCOUNT_SMTP, configurationValues, true);

            // If we don't have a from email, use the "donotreply" address for manywho
            if (String.IsNullOrWhiteSpace(fromEmail) == true)
            {
                fromEmail = defaultEmail;
            }

            // If we don't have a redirection uri, we make it "blank"
            if (String.IsNullOrWhiteSpace(redirectUri) == true)
            {
                redirectUri = "";
            }

            // Construct the email using the provided values
            mailMsg = new MailMessage();

            if (toEmails != null && toEmails.Length > 0)
            {
                // Add each of the emails to the "TO" part
                foreach (String toEmailEntry in toEmails)
                {
                    mailMsg.To.Add(new MailAddress(toEmailEntry, toEmailEntry));
                }
            }

            if (bccEmails != null && bccEmails.Length > 0)
            {
                // Add each of the emails to the "TO" part
                foreach (String bccEmailEntry in bccEmails)
                {
                    mailMsg.Bcc.Add(new MailAddress(bccEmailEntry, bccEmailEntry));
                }
            }

            mailMsg.From    = new MailAddress(fromEmail, fromEmail);
            mailMsg.Subject = subject;

            if (textBody != null &&
                textBody.Trim().Length > 0)
            {
                if (outcomes != null &&
                    outcomes.Count > 0)
                {
                    foreach (OutcomeAvailableAPI outcome in outcomes)
                    {
                        if (outcome.id.Equals(ManyWhoConstants.FAULT_GUID.ToString(), StringComparison.OrdinalIgnoreCase) == false &&
                            string.IsNullOrWhiteSpace(outcome.label) == false)
                        {
                            textBody += outcome.label + "(Click here: " + SettingUtils.GetStringSetting("Salesforce.ServerBasePath") + "/api/email/outcomeresponse?token=" + token + "&selectedOutcomeId=" + outcome.id + "&redirectUri=" + Uri.EscapeUriString(redirectUri) + ")" + Environment.NewLine;
                        }
                    }
                }

                mailMsg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(textBody, null, MediaTypeNames.Text.Plain));
            }

            if (htmlBody != null &&
                htmlBody.Trim().Length > 0)
            {
                fullHtmlBody  = "";
                fullHtmlBody += "<html>";
                fullHtmlBody += "<head>";
                fullHtmlBody += "<script type=\"text/javascript\" src=\"https://assets.manywho.com/js/vendor/bootstrap-3.3.6.min.js\"></script>";
                fullHtmlBody += "<link rel=\"stylesheet\" href=\"https://assets.manywho.com/css/mw-bootstrap.ae817fbf.css\">";
                fullHtmlBody += "<link rel=\"stylesheet\" href=\"https://assets.manywho.com/css/themes/mw-sf1.css\">";
                fullHtmlBody += "</head>";
                fullHtmlBody += "<body class=\"mw-bs\">";
                fullHtmlBody += "<div class=\"container-fluid\">";
                fullHtmlBody += "<div class=\"row\">";
                fullHtmlBody += "<div class=\"col-md-12\">";
                fullHtmlBody += htmlBody;
                fullHtmlBody += "</div>";
                fullHtmlBody += "</div>";

                if (outcomes != null &&
                    outcomes.Count > 0)
                {
                    // The user has outcomes that should be used for actions - sort them before doing anything else
                    outcomes.Sort();

                    fullHtmlBody += "<div class=\"row\">";
                    fullHtmlBody += "<div class=\"col-md-12\">";

                    foreach (OutcomeAvailableAPI outcome in outcomes)
                    {
                        if (outcome.id.Equals(ManyWhoConstants.FAULT_GUID.ToString(), StringComparison.OrdinalIgnoreCase) == false &&
                            string.IsNullOrWhiteSpace(outcome.label) == false)
                        {
                            fullHtmlBody += "<a href=\"" + SettingUtils.GetStringSetting("Salesforce.ServerBasePath") + "/api/email/outcomeresponse?token=" + token + "&selectedOutcomeId=" + outcome.id + "&redirectUri=" + Uri.EscapeUriString(redirectUri) + "\" class=\"btn btn-primary\">" + outcome.label + "</a>&nbsp;";
                        }
                    }

                    fullHtmlBody += "</div>";
                    fullHtmlBody += "</div>";
                }

                fullHtmlBody += "</div>";
                fullHtmlBody += "</body>";
                fullHtmlBody += "</html>";

                mailMsg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(fullHtmlBody, null, MediaTypeNames.Text.Html));
            }

            credentials = new NetworkCredential(emailUsername, emailPassword);

            smtpClient             = new SmtpClient(emailSmtp, Convert.ToInt32(587));
            smtpClient.EnableSsl   = true;
            smtpClient.Credentials = credentials;
            smtpClient.Send(mailMsg);
        }