示例#1
0
        /// <summary>
        /// This method gives a fully qualified url and can be used without an HTTPContext
        /// </summary>
        /// <param name="partialUrl">The partial url to fully qualify eg /images/calendar-icon.png</param>
        /// <returns>The fully qualified web site url</returns>
        public static string GetFullyQualifiedSiteUrl(string partialUrl)
        {
            WorkflowSettingsPoco settings = SettingsService.GetSettings();

            string      editUrl = settings.EditUrl;
            HttpRequest request = HttpContext.Current.Request;

            if (editUrl.HasNoValue())
            {
                if (request.ApplicationPath != null)
                {
                    editUrl = request.Url.Scheme + "://" + request.Url.Authority +
                              request.ApplicationPath.TrimEnd('/') + "/";
                }
            }

            if (editUrl.HasNoValue())
            {
                return(string.Empty);
            }

            bool valid = Uri.TryCreate(editUrl, UriKind.Absolute, out Uri uriResult) &&
                         (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);

            // if result is false, the settings value has no scheme, so prepend from the current request, or fallback to https
            if (!valid)
            {
                editUrl = (request.ApplicationPath.HasValue() ? request.Url.Scheme : Uri.UriSchemeHttps) + "://" + editUrl;
            }

            var baseUrl = new Uri(editUrl);

            return((new Uri(baseUrl, partialUrl)).ToString());
        }
示例#2
0
        public void Returns_New_Settings_If_No_Settings_Exist()
        {
            WorkflowSettingsPoco settings = _repo.GetSettings();

            // email will be populated automatically
            Assert.NotNull(settings);
            Assert.NotNull(settings.Email);
        }
示例#3
0
        public void Returns_Settings_If_Settings_Exist()
        {
            Scaffold.Config();
            WorkflowSettingsPoco settings = _repo.GetSettings();

            Assert.NotNull(settings);
            Assert.Equal("12", settings.DefaultApprover);
        }
示例#4
0
        public Emailer()
        {
            _settings     = new SettingsService().GetSettings();
            _tasksService = new TasksService();
            _groupService = new GroupService();

            _utility = new Utility();
        }
示例#5
0
        public void Can_Get_Settings()
        {
            WorkflowSettingsPoco settings = _service.GetSettings();

            Assert.NotNull(settings);
            Assert.False(settings.LockIfActive);
            Assert.Equal(1, settings.Id);
            Assert.Equal(0, settings.FlowType);
        }
示例#6
0
        protected WorkflowProcess()
        {
            _configService    = new ConfigService();
            _groupService     = new GroupService();
            _instancesService = new InstancesService();
            _settingsService  = new SettingsService();
            _tasksService     = new TasksService();

            _settings = _settingsService.GetSettings();
        }
示例#7
0
        protected WorkflowProcess()
        {
            _configService    = new ConfigService();
            _groupService     = new GroupService();
            _instancesService = new InstancesService();
            _settingsService  = new SettingsService();
            _tasksService     = new TasksService();

            _notifications = new Notifications();
            _utility       = new Utility();
            _settings      = _settingsService.GetSettings();
        }
示例#8
0
 public IHttpActionResult Save(WorkflowSettingsPoco model)
 {
     try
     {
         DatabaseContext.Database.Update(model);
         return(Ok("Settings updated"));
     }
     catch (Exception ex)
     {
         return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex)));
     }
 }
示例#9
0
        protected WorkflowProcess()
        {
            _configService    = new ConfigService();
            _groupService     = new GroupService();
            _instancesService = new InstancesService();
            _settingsService  = new SettingsService();
            _tasksService     = new TasksService();

            _emailer  = new Emailer();
            _utility  = new Utility();
            _settings = _settingsService.GetSettings();
        }
示例#10
0
        public void Can_Update_Settings()
        {
            WorkflowSettingsPoco settings = _repo.GetSettings();
            string defaultApprover        = settings.DefaultApprover;

            settings.DefaultApprover = "15";

            _repo.UpdateSettings(settings);

            settings = _repo.GetSettings();

            Assert.NotEqual(defaultApprover, settings.DefaultApprover);
        }
示例#11
0
 public IHttpActionResult Save(WorkflowSettingsPoco model)
 {
     try
     {
         DatabaseContext.Database.Update(model);
         return(Ok("Settings updated"));
     }
     catch (Exception ex)
     {
         const string error = "Could not save settings";
         Log.Error(error, ex);
         return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, error)));
     }
 }
示例#12
0
 public IHttpActionResult Save(WorkflowSettingsPoco model)
 {
     try
     {
         _settingsService.UpdateSettings(model);
         return(Ok(Constants.SettingsUpdated));
     }
     catch (Exception ex)
     {
         const string error = Constants.SettingsNotUpdated;
         Log.Error(error, ex);
         return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, error)));
     }
 }
示例#13
0
        public IHttpActionResult GetNodePendingTasks(int id)
        {
            // id will be 0 when creating a new page - id is assigned after save
            if (id == 0)
            {
                return(Json(new
                {
                    settings = false,
                    noFlow = false
                }, ViewHelpers.CamelCase));
            }

            try
            {
                WorkflowSettingsPoco settings = _settingsService.GetSettings();
                bool hasFlow = _configService.HasFlow(id);

                if (null == settings || !hasFlow)
                {
                    return(Json(new
                    {
                        settings = settings == null,
                        noFlow = !hasFlow
                    }, ViewHelpers.CamelCase));
                }

                List <WorkflowTaskInstancePoco> taskInstances = _tasksService.GetTasksByNodeId(id);
                if (!taskInstances.Any() || taskInstances.Last().TaskStatus == TaskStatus.Cancelled)
                {
                    return(Json(new
                    {
                        total = 0
                    }, ViewHelpers.CamelCase));
                }

                taskInstances = taskInstances.Where(t => t.TaskStatus.In(TaskStatus.PendingApproval, TaskStatus.Rejected)).ToList();

                return(Json(new
                {
                    items = taskInstances.Any() ? _tasksService.ConvertToWorkflowTaskList(taskInstances) : new List <WorkflowTask>(),
                    total = taskInstances.Count
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"Error getting pending tasks for node {id}";
                Log.Error(msg, ex);
                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
示例#14
0
        public void Can_Update_Settings()
        {
            WorkflowSettingsPoco settings = _service.GetSettings();
            const string         editUrl  = "not.a.real.domain.com";

            settings.FlowType          = 1;
            settings.SendNotifications = !settings.SendNotifications;
            settings.EditUrl           = editUrl;

            _service.UpdateSettings(settings);

            settings = _service.GetSettings();

            Assert.Equal(editUrl, settings.EditUrl);
            Assert.Equal(1, settings.FlowType);
        }
        public async void Can_Update_Settings()
        {
            var model = new WorkflowSettingsPoco
            {
                DefaultApprover   = "12",
                EditUrl           = "some.url.com",
                Email             = "*****@*****.**",
                ExcludeNodes      = "",
                FlowType          = 1,
                SendNotifications = true,
                SiteUrl           = "site.url.com"
            };

            string result = await _settingsController.Save(model).GetContent();

            Assert.Equal(MagicStrings.SettingsUpdated, result);
        }
示例#16
0
        /// <summary>
        /// Get the current workflow settings, or persist an empty instance if none exist
        /// </summary>
        /// <returns>A object of type <see cref="WorkflowSettingsPoco"/> representing the current settings</returns>
        public WorkflowSettingsPoco GetSettings()
        {
            var wsp = new WorkflowSettingsPoco();
            List <WorkflowSettingsPoco> settings = _database.Fetch <WorkflowSettingsPoco>(SqlQueries.GetSettings);

            if (settings.Any())
            {
                wsp = settings.First();
            }
            else
            {
                _database.Insert(wsp);
            }

            if (string.IsNullOrEmpty(wsp.Email))
            {
                wsp.Email = UmbracoConfig.For.UmbracoSettings().Content.NotificationEmailAddress;
            }

            return(wsp);
        }
示例#17
0
        public IHttpActionResult GetNodePendingTasks(int id)
        {
            try
            {
                WorkflowSettingsPoco settings = Pr.GetSettings();
                bool hasFlow = Pr.HasFlow(id);

                if (null == settings || !hasFlow)
                {
                    return(Json(new
                    {
                        settings = settings == null,
                        noFlow = !hasFlow
                    }, ViewHelpers.CamelCase));
                }

                List <WorkflowTaskInstancePoco> taskInstances = Pr.TasksByNode(id);
                if (taskInstances.Last().TaskStatus == TaskStatus.Cancelled)
                {
                    return(Json(new
                    {
                        total = 0
                    }, ViewHelpers.CamelCase));
                }

                taskInstances = taskInstances.Where(t => t.TaskStatus.In(TaskStatus.PendingApproval, TaskStatus.Rejected)).ToList();
                return(Json(new
                {
                    items = taskInstances.Any() ? taskInstances.ToWorkflowTaskList() : new List <WorkflowTask>(),
                    total = taskInstances.Count
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"Error getting pending tasks for node {id}";
                Log.Error(msg, ex);
                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
示例#18
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public WorkflowSettingsPoco GetSettings()
        {
            var wsp      = new WorkflowSettingsPoco();
            var db       = GetDb();
            var settings = db.Fetch <WorkflowSettingsPoco>("SELECT * FROM WorkflowSettings");

            if (settings.Any())
            {
                wsp = settings.First();
            }
            else
            {
                db.Insert(wsp);
            }

            if (string.IsNullOrEmpty(wsp.Email))
            {
                wsp.Email = UmbracoConfig.For.UmbracoSettings().Content.NotificationEmailAddress;
            }

            return(wsp);
        }
示例#19
0
        /// <summary>
        /// This method gives a fully qualified Back Office Edit url
        /// </summary>
        /// <param name="partialUrl">The partial url to fully qualify</param>
        /// <returns>The fully qualified Back Office edit url</returns>
        private static string GetFullyQualifiedEditUrl(string partialUrl)
        {
            WorkflowSettingsPoco settings = SettingsService.GetSettings();
            string editUrl = settings.EditUrl;

            if (editUrl.HasNoValue())
            {
                HttpRequest request = HttpContext.Current.Request;
                if (request.ApplicationPath != null)
                {
                    editUrl = request.Url.Scheme + "://" + request.Url.Authority +
                              request.ApplicationPath.TrimEnd('/') + "/";
                }
            }

            if (editUrl.HasNoValue())
            {
                return(string.Empty);
            }

            var baseUrl = new Uri(editUrl.StartsWith("http") ? editUrl : $"http://{editUrl}");

            return(new Uri(baseUrl, partialUrl).ToString());
        }
示例#20
0
 /// <summary>
 /// Update the workflow settings
 /// </summary>
 /// <param name="settings"></param>
 /// <returns></returns>
 public void UpdateSettings(WorkflowSettingsPoco settings)
 {
     _repo.UpdateSettings(settings);
 }
示例#21
0
 public void UpdateSettings(WorkflowSettingsPoco settings)
 {
     _database.Update(settings);
 }
示例#22
0
        /// <summary>
        /// Sends an email notification out for the workflow process
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="emailType">the type of email to be sent</param>
        public async void Send(WorkflowInstancePoco instance, EmailType emailType)
        {
            WorkflowSettingsPoco settings = _settingsService.GetSettings();

            if (!settings.SendNotifications)
            {
                return;
            }

            if (!instance.TaskInstances.Any())
            {
                instance.TaskInstances = _tasksService.GetTasksWithGroupByInstanceGuid(instance.Guid);
            }

            if (!instance.TaskInstances.Any())
            {
                Log.Error($"Notifications not sent - no tasks exist for instance { instance.Id }");
                return;
            }

            WorkflowTaskPoco finalTask = null;

            try
            {
                string docTitle = instance.Node.Name;
                string docUrl   = UrlHelpers.GetFullyQualifiedContentEditorUrl(instance.NodeId);

                WorkflowTaskPoco[] flowTasks = instance.TaskInstances.OrderBy(t => t.ApprovalStep).ToArray();

                // always take get the emails for all previous users, sometimes they will be discarded later
                // easier to just grab em all, rather than doing so conditionally
                List <string> emailsForAllTaskUsers = new List <string>();

                // in the loop, also store the last task to a variable, and keep the populated group
                var taskIndex = 0;
                int taskCount = flowTasks.Length;

                foreach (WorkflowTaskPoco task in flowTasks)
                {
                    taskIndex += 1;

                    UserGroupPoco group = await _groupService.GetPopulatedUserGroupAsync(task.GroupId);

                    if (group == null)
                    {
                        continue;
                    }

                    emailsForAllTaskUsers.AddRange(group.PreferredEmailAddresses());
                    if (taskIndex != taskCount)
                    {
                        continue;
                    }

                    finalTask           = task;
                    finalTask.UserGroup = group;
                }

                if (finalTask == null)
                {
                    Log.Error("No valid task found for email notifications");
                    return;
                }

                List <string> to = new List <string>();

                var    body                = "";
                string typeDescription     = instance.WorkflowType.Description(instance.ScheduledDate);
                string typeDescriptionPast = instance.WorkflowType.DescriptionPastTense(instance.ScheduledDate);

                switch (emailType)
                {
                case EmailType.ApprovalRequest:
                    to   = finalTask.UserGroup.PreferredEmailAddresses();
                    body = string.Format(EmailApprovalRequestString,
                                         to.Count > 1 ? "Umbraco user" : finalTask.UserGroup.Name, docUrl, docTitle, instance.AuthorComment,
                                         instance.AuthorUser.Name, typeDescription, string.Empty);
                    break;

                case EmailType.ApprovalRejection:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);
                    body = string.Format(EmailRejectedString,
                                         "Umbraco user", docUrl, docTitle, finalTask.Comment,
                                         finalTask.ActionedByUser.Name, typeDescription.ToLower());

                    break;

                case EmailType.ApprovedAndCompleted:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);

                    //Notify web admins
                    to.Add(settings.Email);

                    if (instance.WorkflowType == WorkflowType.Publish)
                    {
                        IPublishedContent n = _utility.GetPublishedContent(instance.NodeId);
                        docUrl = UrlHelpers.GetFullyQualifiedSiteUrl(n.Url);
                    }

                    body = string.Format(EmailApprovedString,
                                         "Umbraco user", docUrl, docTitle,
                                         typeDescriptionPast.ToLower()) + "<br/>";

                    body += instance.BuildProcessSummary();

                    break;

                case EmailType.ApprovedAndCompletedForScheduler:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);

                    body = string.Format(EmailApprovedString,
                                         "Umbraco user", docUrl, docTitle,
                                         typeDescriptionPast.ToLower()) + "<br/>";

                    body += instance.BuildProcessSummary();

                    break;

                case EmailType.WorkflowCancelled:
                    to = emailsForAllTaskUsers;

                    // include the initiator email
                    to.Add(instance.AuthorUser.Email);

                    body = string.Format(EmailCancelledString,
                                         "Umbraco user", typeDescription, docUrl, docTitle, finalTask.ActionedByUser.Name, finalTask.Comment);
                    break;

                case EmailType.SchedulerActionCancelled:
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(emailType), emailType, null);
                }

                if (!to.Any())
                {
                    return;
                }

                var client = new SmtpClient();
                var msg    = new MailMessage
                {
                    Subject    = $"{emailType.ToString().ToTitleCase()} - {instance.Node.Name} ({typeDescription})",
                    IsBodyHtml = true,
                };

                if (settings.Email.HasValue())
                {
                    msg.From = new MailAddress(settings.Email);
                }

                // if offline is permitted, email group members individually as we need the user id in the url
                if (emailType == EmailType.ApprovalRequest && finalTask.UserGroup.OfflineApproval)
                {
                    foreach (User2UserGroupPoco user in finalTask.UserGroup.Users)
                    {
                        string offlineString = string.Format(EmailOfflineApprovalString, settings.SiteUrl, instance.NodeId,
                                                             user.UserId, finalTask.Id, instance.Guid);

                        body = string.Format(EmailApprovalRequestString,
                                             user.User.Name, docUrl, docTitle, instance.AuthorComment,
                                             instance.AuthorUser.Name, typeDescription, offlineString);

                        msg.To.Clear();
                        msg.To.Add(user.User.Email);
                        msg.Body = string.Format(EmailBody, msg.Subject, body);

                        client.Send(msg);
                    }
                }
                else
                {
                    msg.To.Add(string.Join(",", to.Distinct()));
                    msg.Body = string.Format(EmailBody, msg.Subject, body);

                    client.Send(msg);
                }

                Log.Info($"Email notifications sent for task { finalTask.Id }, to { msg.To }");
            }
            catch (Exception e)
            {
                Log.Error($"Error sending notifications for task { finalTask.Id }", e);
            }
        }
 public SettingsEventArgs(WorkflowSettingsPoco settings)
 {
     Settings = settings;
 }
示例#24
0
        /// <summary>
        /// Get the workflow settings
        /// </summary>
        /// <returns></returns>
        public WorkflowSettingsPoco GetSettings()
        {
            WorkflowSettingsPoco settings = _repo.GetSettings();

            return(settings);
        }
示例#25
0
 /// <summary>
 /// Update the workflow settings
 /// </summary>
 /// <param name="settings"></param>
 /// <returns></returns>
 public void UpdateSettings(WorkflowSettingsPoco settings)
 {
     _repo.UpdateSettings(settings);
     Updated?.Invoke(this, new SettingsEventArgs(settings));
 }
示例#26
0
        /// <summary>
        /// Sends an email notification out for the workflow process
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="emailType">the type of email to be sent</param>
        public async void Send(WorkflowInstancePoco instance, EmailType emailType)
        {
            WorkflowSettingsPoco settings = _settingsService.GetSettings();

            bool?doSend = settings.SendNotifications;

            if (doSend != true)
            {
                return;
            }

            if (!instance.TaskInstances.Any())
            {
                instance.TaskInstances = _tasksService.GetTasksWithGroupByInstanceGuid(instance.Guid);
            }

            try
            {
                string docTitle = instance.Node.Name;
                string docUrl   = UrlHelpers.GetFullyQualifiedContentEditorUrl(instance.NodeId);

                IOrderedEnumerable <WorkflowTaskInstancePoco> flowTasks = instance.TaskInstances.OrderBy(t => t.ApprovalStep);

                // always take get the emails for all previous users, sometimes they will be discarded later
                // easier to just grab em all, rather than doing so conditionally
                List <string> emailsForAllTaskUsers = new List <string>();

                // in the loop, also store the last task to a variable, and keep the populated group
                var taskIndex = 0;
                int taskCount = flowTasks.Count();

                WorkflowTaskInstancePoco finalTask = null;

                foreach (WorkflowTaskInstancePoco task in flowTasks)
                {
                    taskIndex += 1;

                    UserGroupPoco group = await _groupService.GetPopulatedUserGroupAsync(task.GroupId);

                    if (group == null)
                    {
                        continue;
                    }

                    emailsForAllTaskUsers.AddRange(group.PreferredEmailAddresses());
                    if (taskIndex != taskCount)
                    {
                        continue;
                    }

                    finalTask           = task;
                    finalTask.UserGroup = group;
                }

                List <string> to = new List <string>();
                string        systemEmailAddress = settings.Email;

                var body = "";

                switch (emailType)
                {
                case EmailType.ApprovalRequest:
                    to   = finalTask.UserGroup.PreferredEmailAddresses();
                    body = string.Format(EmailApprovalRequestString,
                                         to.Count > 1 ? "Umbraco user" : finalTask.UserGroup.Name, docUrl, docTitle, instance.AuthorComment,
                                         instance.AuthorUser.Name, instance.TypeDescription);

                    break;

                case EmailType.ApprovalRejection:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);
                    body = string.Format(EmailRejectedString,
                                         "Umbraco user", docUrl, docTitle, finalTask.Comment,
                                         finalTask.ActionedByUser.Name, instance.TypeDescription.ToLower());

                    break;

                case EmailType.ApprovedAndCompleted:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);

                    //Notify web admins
                    to.Add(systemEmailAddress);

                    if (instance.WorkflowType == WorkflowType.Publish)
                    {
                        IPublishedContent n = _utility.GetPublishedContent(instance.NodeId);
                        docUrl = UrlHelpers.GetFullyQualifiedSiteUrl(n.Url);
                    }

                    body = string.Format(EmailApprovedString,
                                         "Umbraco user", docUrl, docTitle,
                                         instance.TypeDescriptionPastTense.ToLower()) + "<br/>";

                    body += BuildProcessSummary(instance);

                    break;

                case EmailType.ApprovedAndCompletedForScheduler:
                    to = emailsForAllTaskUsers;
                    to.Add(instance.AuthorUser.Email);

                    body = string.Format(EmailApprovedString,
                                         "Umbraco user", docUrl, docTitle,
                                         instance.TypeDescriptionPastTense.ToLower()) + "<br/>";

                    body += BuildProcessSummary(instance);

                    break;

                case EmailType.WorkflowCancelled:
                    to = emailsForAllTaskUsers;

                    // include the initiator email
                    to.Add(instance.AuthorUser.Email);

                    body = string.Format(EmailCancelledString,
                                         "Umbraco user", instance.TypeDescription, docUrl, docTitle, finalTask.ActionedByUser.Name, finalTask.Comment);
                    break;

                case EmailType.SchedulerActionCancelled:
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(emailType), emailType, null);
                }

                if (!to.Any())
                {
                    return;
                }

                var client = new SmtpClient();
                var msg    = new MailMessage();

                if (!string.IsNullOrEmpty(systemEmailAddress))
                {
                    msg.From = new MailAddress(systemEmailAddress);
                }

                string subject = BuildEmailSubject(emailType, instance);

                msg.To.Add(string.Join(",", to.Distinct()));
                msg.Subject    = subject;
                msg.Body       = $"<!DOCTYPE HTML SYSTEM><html><head><title>{subject}</title></head><body><font face=\"verdana\" size=\"2\">{body}</font></body></html>";
                msg.IsBodyHtml = true;

                client.Send(msg);
            }
            catch (Exception e)
            {
                Log.Error("Error sending notifications", e);
            }
        }