public async Task ExecuteAsync(RecipeExecutionContext context)
        {
            if (!String.Equals(context.Name, "WorkflowType", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var model = context.Step.ToObject <WorkflowStepModel>();

            foreach (JObject token in model.Data)
            {
                var workflow = token.ToObject <WorkflowType>();

                var existing = await _workflowTypeStore.GetAsync(workflow.WorkflowTypeId);

                if (existing == null)
                {
                    workflow.Id = 0;
                }
                else
                {
                    await _workflowTypeStore.DeleteAsync(existing);
                }

                await _workflowTypeStore.SaveAsync(workflow);
            }
        }
        public async Task <WorkflowExecutionContext> ResumeWorkflowAsync(Workflow workflow,
                                                                         BlockingActivity awaitingActivity, IDictionary <string, object> input = null)
        {
            var workflowType = await _workflowTypeStore.GetAsync(workflow.WorkflowTypeId);

            var activityRecord =
                workflowType.Activities.SingleOrDefault(x => x.ActivityId == awaitingActivity.ActivityId);
            var workflowContext = await CreateWorkflowExecutionContextAsync(workflowType, workflow, input);

            workflowContext.Status = WorkflowStatus.Resuming;

            // Signal every activity that the workflow is about to be resumed.
            var cancellationToken = new CancellationToken();

            await InvokeActivitiesAsync(workflowContext, x => x.Activity.OnInputReceivedAsync(workflowContext, input));
            await InvokeActivitiesAsync(workflowContext,
                                        x => x.Activity.OnWorkflowResumingAsync(workflowContext, cancellationToken));

            if (cancellationToken.IsCancellationRequested)
            {
                // Workflow is aborted.
                workflowContext.Status = WorkflowStatus.Aborted;
            }
            else
            {
                // Check if the current activity can execute.
                if (activityRecord != null)
                {
                    var activityContext = workflowContext.GetActivity(activityRecord.ActivityId);
                    if (await activityContext.Activity.CanExecuteAsync(workflowContext, activityContext))
                    {
                        // Signal every activity that the workflow is resumed.
                        await InvokeActivitiesAsync(workflowContext,
                                                    x => x.Activity.OnWorkflowResumedAsync(workflowContext));

                        // Remove the blocking activity.
                        workflowContext.Workflow.BlockingActivities.Remove(awaitingActivity);

                        // Resume the workflow at the specified blocking activity.
                        await ExecuteWorkflowAsync(workflowContext, activityRecord);
                    }
                    else
                    {
                        workflowContext.Status = WorkflowStatus.Halted;
                        return(workflowContext);
                    }
                }
            }

            if (workflowContext.Status == WorkflowStatus.Finished && workflowType.DeleteFinishedWorkflows)
            {
                await _workflowStore.DeleteAsync(workflowContext.Workflow);
            }
            else
            {
                await PersistAsync(workflowContext);
            }

            return(workflowContext);
        }
        private async Task UpdateRouteEntriesAsync(WorkflowContext context)
        {
            var workflow     = context.Workflow;
            var workflowType = await _workflowTypeStore.GetAsync(workflow.WorkflowTypeId);

            var entries = WorkflowRouteEntries.GetWorkflowRoutesEntries(workflowType, context.Workflow, _activityLibrary);

            _workflowRouteEntries.AddEntries(entries);
        }
        public async Task <IActionResult> BulkEdit(WorkflowTypeBulkAction bulkAction, PagerParameters pagerParameters)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Unauthorized());
            }

            var viewModel = new WorkflowTypeIndexViewModel {
                WorkflowTypes = new List <WorkflowTypeEntry>(), Options = new WorkflowTypeIndexOptions()
            };

            if (!(await TryUpdateModelAsync(viewModel)))
            {
                return(View(viewModel));
            }

            var checkedEntries = viewModel.WorkflowTypes.Where(t => t.IsChecked);

            switch (bulkAction)
            {
            case WorkflowTypeBulkAction.None:
                break;

            case WorkflowTypeBulkAction.Delete:
                foreach (var entry in checkedEntries)
                {
                    var workflowType = await _workflowTypeStore.GetAsync(entry.Id);

                    if (workflowType != null)
                    {
                        await _workflowTypeStore.DeleteAsync(workflowType);

                        _notifier.Success(H["Workflow {0} has been deleted.", workflowType.Name]);
                    }
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(RedirectToAction("Index", new { page = pagerParameters.Page, pageSize = pagerParameters.PageSize }));
        }
Beispiel #5
0
        public async Task <IActionResult> GenerateUrl(int workflowTypeId, string activityId, int tokenLifeSpan)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Forbid());
            }

            var workflowType = await _workflowTypeStore.GetAsync(workflowTypeId);

            if (workflowType == null)
            {
                return(NotFound());
            }

            var token = _securityTokenService.CreateToken(new WorkflowPayload(workflowType.WorkflowTypeId, activityId), TimeSpan.FromDays(tokenLifeSpan == 0 ? NoExpiryTokenLifespan : tokenLifeSpan));
            var url   = Url.Action("Invoke", "HttpWorkflow", new { token = token });

            return(Ok(url));
        }
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var httpMethod          = context.HttpContext.Request.Method;
            var routeValues         = context.RouteData.Values;
            var workflowTypeEntries = await _workflowTypeRouteEntries.GetWorkflowRouteEntriesAsync(httpMethod, routeValues);

            var workflowEntries = await _workflowRouteEntries.GetWorkflowRouteEntriesAsync(httpMethod, routeValues);

            if (workflowTypeEntries.Any())
            {
                var workflowTypeIds = workflowTypeEntries.Select(x => Int32.Parse(x.WorkflowId)).ToList();
                var workflowTypes   = (await _workflowTypeStore.GetAsync(workflowTypeIds)).ToDictionary(x => x.Id);
                var correlationId   = routeValues.GetValue <string>("correlationid");

                foreach (var entry in workflowTypeEntries)
                {
                    if (workflowTypes.TryGetValue(Int32.Parse(entry.WorkflowId), out var workflowType))
                    {
                        var activity = workflowType.Activities.Single(x => x.ActivityId == entry.ActivityId);

                        if (activity.IsStart)
                        {
                            // If this is not a singleton workflow or there is not already an halted instance, start a new workflow.
                            if (!workflowType.IsSingleton || !await _workflowStore.HasHaltedInstanceAsync(workflowType.WorkflowTypeId))
                            {
                                await _workflowManager.StartWorkflowAsync(workflowType, activity, null, correlationId);
                            }
                        }
                    }
                }
            }

            if (workflowEntries.Any())
            {
                var workflowIds   = workflowEntries.Select(x => x.WorkflowId).ToList();
                var workflows     = (await _workflowStore.GetAsync(workflowIds)).ToDictionary(x => x.WorkflowId);
                var correlationId = routeValues.GetValue <string>("correlationid");

                foreach (var entry in workflowEntries)
                {
                    if (workflows.TryGetValue(entry.WorkflowId, out var workflow) &&
                        (String.IsNullOrWhiteSpace(correlationId) ||
                         workflow.CorrelationId == correlationId))
                    {
                        var blockingActivity = workflow.BlockingActivities.Single(x => x.ActivityId == entry.ActivityId);
                        await _workflowManager.ResumeWorkflowAsync(workflow, blockingActivity);
                    }
                }
            }

            await next();
        }
Beispiel #7
0
        public async Task <IActionResult> BulkEdit(WorkflowTypeIndexOptions options, IEnumerable <int> itemIds)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Forbid());
            }

            if (itemIds?.Count() > 0)
            {
                var checkedEntries = await _session.Query <WorkflowType, WorkflowTypeIndex>().Where(x => x.DocumentId.IsIn(itemIds)).ListAsync();

                switch (options.BulkAction)
                {
                case WorkflowTypeBulkAction.None:
                    break;

                case WorkflowTypeBulkAction.Delete:
                    foreach (var entry in checkedEntries)
                    {
                        var workflowType = await _workflowTypeStore.GetAsync(entry.Id);

                        if (workflowType != null)
                        {
                            await _workflowTypeStore.DeleteAsync(workflowType);

                            _notifier.Success(H["Workflow {0} has been deleted.", workflowType.Name]);
                        }
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return(RedirectToAction("Index"));
        }
Beispiel #8
0
        public async Task <IActionResult> Index(int workflowTypeId, PagerParameters pagerParameters, string returnUrl = null)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Unauthorized());
            }

            if (!Url.IsLocalUrl(returnUrl))
            {
                returnUrl = Url.Action(nameof(Index), "WorkflowType");
            }

            var workflowType = await _workflowTypeStore.GetAsync(workflowTypeId);

            var siteSettings = await _siteService.GetSiteSettingsAsync();

            var count = await _workflowStore.CountAsync(workflowType.WorkflowTypeId);

            var pager   = new Pager(pagerParameters, siteSettings.PageSize);
            var records = await _workflowStore.ListAsync(workflowType.WorkflowTypeId, pager.GetStartIndex(), pager.PageSize);

            var pagerShape = (await New.Pager(pager)).TotalItemCount(count);

            var viewModel = new WorkflowIndexViewModel
            {
                WorkflowType = workflowType,
                Workflows    = records.Select(x => new WorkflowEntry
                {
                    Workflow = x,
                    Id       = x.Id
                }).ToList(),
                Pager     = pagerShape,
                ReturnUrl = returnUrl
            };

            return(View(viewModel));
        }
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var httpMethod          = context.HttpContext.Request.Method;
            var routeValues         = context.RouteData.Values;
            var workflowTypeEntries = _workflowTypeRouteEntries.GetWorkflowRouteEntries(httpMethod, routeValues);
            var workflowEntries     = _workflowRouteEntries.GetWorkflowRouteEntries(httpMethod, routeValues);

            if (workflowTypeEntries.Any())
            {
                var workflowTypeIds = workflowTypeEntries.Select(x => Int32.Parse(x.WorkflowId)).ToList();
                var workflowTypes   = (await _workflowTypeStore.GetAsync(workflowTypeIds)).ToDictionary(x => x.Id);

                foreach (var entry in workflowTypeEntries)
                {
                    var workflowType = workflowTypes[Int32.Parse(entry.WorkflowId)];
                    var activity     = workflowType.Activities.Single(x => x.ActivityId == entry.ActivityId);
                    await _workflowManager.StartWorkflowAsync(workflowType, activity);
                }
            }

            await next();
        }
        public async Task <IActionResult> Index(int workflowTypeId, WorkflowIndexViewModel model, PagerParameters pagerParameters, string returnUrl = null)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Forbid());
            }

            if (!Url.IsLocalUrl(returnUrl))
            {
                returnUrl = Url.Action(nameof(Index), "WorkflowType");
            }

            var workflowType = await _workflowTypeStore.GetAsync(workflowTypeId);

            var siteSettings = await _siteService.GetSiteSettingsAsync();

            var query = _session.Query <Workflow, WorkflowIndex>();

            query = query.Where(x => x.WorkflowTypeId == workflowType.WorkflowTypeId);

            switch (model.Options.Filter)
            {
            case WorkflowFilter.Finished:
                query = query.Where(x => x.WorkflowStatus == WorkflowStatus.Finished);
                break;

            case WorkflowFilter.Faulted:
                query = query.Where(x => x.WorkflowStatus == WorkflowStatus.Faulted);
                break;

            case WorkflowFilter.All:
            default:
                break;
            }

            switch (model.Options.OrderBy)
            {
            case WorkflowOrder.CreatedDesc:
                query = query.OrderByDescending(x => x.CreatedUtc);
                break;

            case WorkflowOrder.Created:
                query = query.OrderBy(x => x.CreatedUtc);
                break;

            default:
                query = query.OrderByDescending(x => x.CreatedUtc);
                break;
            }

            var pager = new Pager(pagerParameters, siteSettings.PageSize);

            var routeData = new RouteData();

            routeData.Values.Add("Filter", model.Options.Filter);

            var pagerShape  = (await New.Pager(pager)).TotalItemCount(await query.CountAsync()).RouteData(routeData);
            var pageOfItems = await query.Skip(pager.GetStartIndex()).Take(pager.PageSize).ListAsync();

            var viewModel = new WorkflowIndexViewModel
            {
                WorkflowType = workflowType,
                Workflows    = pageOfItems.Select(x => new WorkflowEntry
                {
                    Workflow = x,
                    Id       = x.Id
                }).ToList(),
                Options   = model.Options,
                Pager     = pagerShape,
                ReturnUrl = returnUrl
            };

            model.Options.WorkflowsSorts = new List <SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = S["Recently created"], Value = nameof(WorkflowOrder.CreatedDesc)
                },
                new SelectListItem()
                {
                    Text = S["Least recently created"], Value = nameof(WorkflowOrder.Created)
                }
            };

            model.Options.WorkflowsStatuses = new List <SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = S["All"], Value = nameof(WorkflowFilter.All)
                },
                new SelectListItem()
                {
                    Text = S["Faulted"], Value = nameof(WorkflowFilter.Faulted)
                },
                new SelectListItem()
                {
                    Text = S["Finished"], Value = nameof(WorkflowFilter.Finished)
                }
            };

            viewModel.Options.WorkflowsBulkAction = new List <SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = S["Delete"], Value = nameof(WorkflowBulkAction.Delete)
                }
            };

            return(View(viewModel));
        }
Beispiel #11
0
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var httpMethod          = context.HttpContext.Request.Method;
            var routeValues         = context.RouteData.Values;
            var workflowTypeEntries = await _workflowTypeRouteEntries.GetWorkflowRouteEntriesAsync(httpMethod, routeValues);

            var workflowEntries = await _workflowRouteEntries.GetWorkflowRouteEntriesAsync(httpMethod, routeValues);

            if (workflowTypeEntries.Any())
            {
                var workflowTypeIds = workflowTypeEntries.Select(x => Int32.Parse(x.WorkflowId)).ToList();
                var workflowTypes   = (await _workflowTypeStore.GetAsync(workflowTypeIds)).ToDictionary(x => x.Id);
                var correlationId   = routeValues.GetValue <string>("correlationid");

                foreach (var entry in workflowTypeEntries)
                {
                    if (workflowTypes.TryGetValue(Int32.Parse(entry.WorkflowId), out var workflowType))
                    {
                        var activity = workflowType.Activities.Single(x => x.ActivityId == entry.ActivityId);

                        if (activity.IsStart)
                        {
                            // If a singleton, try to acquire a lock per workflow type.
                            (var locker, var locked) = await _distributedLock.TryAcquireWorkflowTypeLockAsync(workflowType);

                            if (!locked)
                            {
                                continue;
                            }

                            await using var acquiredLock = locker;

                            // Check if this is a workflow singleton and there's already an halted instance on any activity.
                            if (workflowType.IsSingleton && await _workflowStore.HasHaltedInstanceAsync(workflowType.WorkflowTypeId))
                            {
                                continue;
                            }

                            await _workflowManager.StartWorkflowAsync(workflowType, activity, null, correlationId);
                        }
                    }
                }
            }

            if (workflowEntries.Any())
            {
                var workflowIds   = workflowEntries.Select(x => x.WorkflowId).ToList();
                var workflows     = (await _workflowStore.GetAsync(workflowIds)).ToDictionary(x => x.WorkflowId);
                var correlationId = routeValues.GetValue <string>("correlationid");

                foreach (var entry in workflowEntries)
                {
                    if (workflows.TryGetValue(entry.WorkflowId, out var workflow) &&
                        (String.IsNullOrWhiteSpace(correlationId) ||
                         workflow.CorrelationId == correlationId))
                    {
                        // If atomic, try to acquire a lock per workflow instance.
                        (var locker, var locked) = await _distributedLock.TryAcquireWorkflowLockAsync(workflow);

                        if (!locked)
                        {
                            continue;
                        }

                        await using var acquiredLock = locker;

                        // If atomic, check if the workflow still exists and is still correlated.
                        var haltedWorkflow = workflow.IsAtomic ? await _workflowStore.GetAsync(workflow.Id) : workflow;

                        if (haltedWorkflow == null || (!String.IsNullOrWhiteSpace(correlationId) && haltedWorkflow.CorrelationId != correlationId))
                        {
                            continue;
                        }

                        // And if it is still halted on this activity.
                        var blockingActivity = haltedWorkflow.BlockingActivities.SingleOrDefault(x => x.ActivityId == entry.ActivityId);
                        if (blockingActivity != null)
                        {
                            await _workflowManager.ResumeWorkflowAsync(haltedWorkflow, blockingActivity);
                        }
                    }
                }
            }

            await next();
        }
        public async Task <IActionResult> InsertSnippet(string workflowsnippetname, int workflowTypeId, string returnUrl)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
            {
                return(Forbid());
            }

            var workflowSnippet = await  GetWorkFlowSnippet(workflowsnippetname);

            var sourceworkflowSnippetToInsert = workflowSnippet.WorkFlowType;

            var targetWorkflowType = await _workflowTypeStore.GetAsync(workflowTypeId);

            //copy source workflow into target workflow and save
            foreach (var act in sourceworkflowSnippetToInsert.Activities)
            {
                targetWorkflowType.Activities.Add(new ActivityRecord()
                {
                    ActivityId = act.ActivityId,
                    Name       = act.Name,
                    Properties = act.Properties,
                    X          = act.X,
                    Y          = act.Y,
                    IsStart    = act.IsStart
                });
            }

            foreach (var trans in sourceworkflowSnippetToInsert.Transitions)
            {
                targetWorkflowType.Transitions.Add(new Transition
                {
                    Id = trans.Id,
                    SourceActivityId      = trans.SourceActivityId,
                    DestinationActivityId = trans.DestinationActivityId,
                    SourceOutcomeName     = trans.SourceOutcomeName
                });
            }

            await _workflowTypeStore.SaveAsync(targetWorkflowType);

            // No editor to show; short-circuit to the "POST" action.
            return(Url.IsLocalUrl(returnUrl) ? (IActionResult)Redirect(returnUrl) : RedirectToAction("Edit", "WorkflowType", new { id = workflowTypeId }));

            /*//var activity = _activityLibrary.InstantiateActivity(activityName);
             * var activityId = _activityIdGenerator.GenerateUniqueId(new ActivityRecord());
             * var activityEditor = await _activityDisplayManager.BuildEditorAsync(activity, _updateModelAccessor.ModelUpdater, isNew: true);
             *
             * activityEditor.Metadata.Type = "Activity_Edit";
             *
             * var viewModel = new ActivityEditViewModel
             * {
             *  Activity = activity,
             *  ActivityId = activityId,
             *  ActivityEditor = activityEditor,
             *  WorkflowTypeId = workflowTypeId,
             *  ReturnUrl = returnUrl
             * };
             *
             * if (!activity.HasEditor)
             * {
             *  // No editor to show; short-circuit to the "POST" action.
             *  return await Create(activityName, viewModel);
             * }
             *
             * return View(viewModel);*/
        }