private void ResumeWorkflowRun(PromptUserTask task, List <Action> actions) { var workflowRun = task.WorkflowRunForTask; if ((task.UserTaskIsComplete ?? false) && (workflowRun != null) && (workflowRun.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunPaused)) { var resumeEvent = new PromptUserTaskCompletedEvent { UserTaskId = task.Id }; actions.Add(() => { using (new WorkflowRunContext(true) { RunTriggersInCurrentThread = true }) // need to ensure that all deferred saves occur before we register complete. { WorkflowRunner.Instance.ResumeWorkflow(workflowRun, resumeEvent); } }); } }
/// <summary> /// Start the activity running /// </summary> /// <returns>True if the activity has completed, false if it is paused. Along with a sequence number of if it is paused</returns> public override bool OnStart(IRunState context, ActivityInputs inputs) { var assignedTo = GetArgumentEntity <Person>(inputs, "inPromptUserForPerson"); var promptMessage = GetArgumentValue <string>(inputs, "inPromptUserMessage"); var activityInstanceAs = ActivityInstance.Cast <PromptUserActivity>(); var userTask = new PromptUserTask { Name = ActivityInstance.Name ?? "User input required", AssignedToUser = assignedTo, TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusNotStarted, UserTaskDueOn = DateTime.UtcNow, // dueDate KeepAfterCompletion = false, // keepTask WaitForNextTask = true, // waitForNext PromptForTaskMessage = promptMessage, PromptForTaskArguments = new EntityCollection <ActivityPrompt>(activityInstanceAs.PromptForArguments) }; // move current state information on to the task for pre-population of any arguments for prompt var argValues = context.GetArgValues().ToList(); foreach (var arg in activityInstanceAs.PromptForArguments) { var argValue = argValues.FirstOrDefault(a => a.Item2.Id == arg.ActivityPromptArgument.Id); if (argValue != null) { var valueArg = ActivityArgumentHelper.ConvertArgInstValue(argValue.Item1, argValue.Item2, argValue.Item3); userTask.PromptForTaskStateInfo.Add(new StateInfoEntry { Name = valueArg.Name, StateInfoActivity = ActivityInstance, StateInfoArgument = argValue.Item2, StateInfoValue = valueArg }); continue; } var emptyArg = ActivityArgumentHelper.ConvertArgInstValue(ActivityInstance, arg.ActivityPromptArgument, null); userTask.PromptForTaskStateInfo.Add(new StateInfoEntry { Name = emptyArg.Name, StateInfoActivity = ActivityInstance, StateInfoArgument = arg.ActivityPromptArgument, StateInfoValue = emptyArg }); } context.SetUserTask(userTask.Cast <BaseUserTask>()); return(false); }
public void LowAccessUserPausedPriorNestedWorkflow_bug_27863() { using (new WorkflowRunContext { RunTriggersInCurrentThread = true }) { Workflow myParentWorkflow = null; Workflow myChildWorkflow = null; UserAccount myUser = null; Person myPerson = null; PromptUserTask userInputTask = null; try { myChildWorkflow = Entity.Create <Workflow>() .AddDefaultExitPoint() .AddInput <BoolArgument>("InputChild") .AddLog("Child Log", "Child Log"); myChildWorkflow.Name = "Child Workflow 27863 " + DateTime.Now; myChildWorkflow.WorkflowRunAsOwner = true; myChildWorkflow.Save(); myParentWorkflow = Entity.Create <Workflow>() .AddDefaultExitPoint() .AddInput <BoolArgument>("InputParent") .AddPromptUser("User Input") .AddWorkflowProxy("Child Workflow", myChildWorkflow) .AddLog("Parent Log", "Parent Log"); var childWorkflowActivity = myParentWorkflow.ContainedActivities.FirstOrDefault(a => a.Name == "Child Workflow"); ActivityTestHelper.AddExpressionToActivityArgument(myParentWorkflow, childWorkflowActivity, "InputChild", "[InputParent]"); myParentWorkflow.Name = "Parent Workflow 27863 " + DateTime.Now; myParentWorkflow.WorkflowRunAsOwner = true; myParentWorkflow.Save(); myPerson = Entity.Create <Person>(); myPerson.FirstName = "Billy"; myPerson.LastName = "Bob"; myUser = Entity.Create <UserAccount>(); myUser.Name = "bb" + DateTime.Now; myUser.AccountHolder = myPerson; myUser.Save(); new AccessRuleFactory().AddAllowByQuery(myUser.As <Subject>(), Workflow.Workflow_Type.As <SecurableEntity>(), new EntityRef("core:read").ToEnumerable(), TestQueries.Entities(new EntityRef("core:workflow")).ToReport()); WorkflowRun run; using (new SetUser(myUser)) using (new WorkflowRunContext(true) { RunTriggersInCurrentThread = true }) { run = RunWorkflow(myParentWorkflow); } run.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused); run.PendingActivity.Should().NotBeNull(); run.PendingActivity.Name.Should().Be("User Input"); run.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1); userInputTask = run.TaskWithinWorkflowRun.First().AsWritable <PromptUserTask>(); userInputTask.Should().NotBeNull(); userInputTask.PromptForTaskStateInfo.Should().NotBeNull().And.HaveCount(1); userInputTask.PromptForTaskStateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("InputParent"); var value = userInputTask.PromptForTaskStateInfo.First(si => si.StateInfoArgument.Name == "InputParent"); var param = value.StateInfoValue.AsWritable <BoolArgument>(); param.BoolParameterValue = true; param.Save(); userInputTask.TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusCompleted; userInputTask.UserTaskIsComplete = true; using (new SetUser(myUser)) using (new WorkflowRunContext(true) { RunTriggersInCurrentThread = true }) { userInputTask.Save(); } var wf = Entity.Get <Workflow>(myParentWorkflow.Id, Workflow.RunningInstances_Field); wf.RunningInstances.Count().Should().Be(1); var runResume = wf.RunningInstances.First(); Assert.IsTrue(WaitForWorkflowToStop(runResume), "Workflow run should have completed."); runResume = Entity.Get <WorkflowRun>(runResume.Id, WorkflowRun.WorkflowRunStatus_Field); runResume.Should().NotBeNull(); runResume.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunCompleted); runResume.RunLog.Should().NotBeNull().And.NotBeEmpty(); } finally { if (userInputTask != null) { ToDelete.Add(userInputTask.Id); } if (myParentWorkflow != null) { ToDelete.Add(myParentWorkflow.Id); } if (myChildWorkflow != null) { ToDelete.Add(myChildWorkflow.Id); } if (myUser != null) { ToDelete.Add(myUser.Id); } if (myPerson != null) { ToDelete.Add(myPerson.Id); } } } }
public void TestDisplayFormResumeWithPromptActivity_Bug_27060() { using (new WorkflowRunContext { RunTriggersInCurrentThread = true }) { Workflow wf = null; DisplayFormUserTask task = null; PromptUserTask p = null; try { WorkflowRun run, run2, run3; // Arrange var cheese = new EntityRef("test", "cheese"); var cheeses = Entity.GetInstancesOfType(cheese); // // IMPORTANT: the point is to NOT set a value on the variable for this test! // the run state serialization that occurs when pausing must realize that the variable is used // subsequently. // wf = Entity.Create <Workflow>() .AddDefaultExitPoint() .AddVariable <ResourceArgument>("myVar", null, Entity.Get <EntityType>(new EntityRef("test", "employee"))) //.AddEntityExpressionToVariable("myVar", new EntityRef("test", "aaJudeJacobs")) .AddInput <ResourceArgument>("myInput", Entity.Get <EntityType>(cheese)) .AddDisplayForm("Display Form", new[] { "Exit1", "Exit2" }, recordExpression: "[myInput]") .AddPromptUser("Prompt User") .AddLog("Log", "MyVar: {{myVar}}"); wf.Name = "!TestDisplayFormResumeWithVariables_Bug_23903_" + DateTime.Now; wf.Save(); // Act var wfInput = new Dictionary <string, object> { { "myInput", cheeses.First() } }; using (new WorkflowRunContext(true)) { run = RunWorkflow(wf, wfInput); } run.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused); run.PendingActivity.Should().NotBeNull(); run.PendingActivity.Name.Should().Be("Display Form"); run.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1); task = run.TaskWithinWorkflowRun.First().AsWritable <DisplayFormUserTask>(); task.Should().NotBeNull(); run.StateInfo.Count.Should().BeGreaterOrEqualTo(2); run.StateInfo.Select(si => si.StateInfoArgument.Name).Should().NotContain("myVar"); run.StateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput"); using (new WorkflowRunContext(true)) { run2 = WorkflowRunner.Instance.ResumeWorkflow(run, new UserCompletesTaskEvent { CompletionStateId = task.AvailableTransitions.First(t => t.Name == "Exit1").Id, UserTaskId = task.Id }); } run2.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused); run2.PendingActivity.Should().NotBeNull(); run2.PendingActivity.Name.Should().Be("Prompt User"); run2.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1); p = run2.TaskWithinWorkflowRun.First().AsWritable <PromptUserTask>(); p.Should().NotBeNull(); p.PromptForTaskStateInfo.Should().NotBeNull().And.HaveCount(2); p.PromptForTaskStateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myVar"); p.PromptForTaskStateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput"); run2.StateInfo.Count.Should().BeGreaterOrEqualTo(3); run2.StateInfo.Select(si => si.StateInfoArgument.Name).Should().NotContain("myVar"); run2.StateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput"); var value = p.PromptForTaskStateInfo.First(si => si.StateInfoArgument.Name == "myVar"); var param = value.StateInfoValue.AsWritable <ResourceArgument>(); param.ResourceParameterValue = Entity.Get <Resource>(new EntityRef("test", "aaJudeJacobs")); param.Save(); var param2 = Entity.Get <ResourceArgument>(param); param2.ResourceParameterValue.Should().NotBeNull(); param2.ResourceParameterValue.Name.Should().Be("Jude Jacobs"); using (new WorkflowRunContext(true)) { run3 = WorkflowRunner.Instance.ResumeWorkflow(run2, new PromptUserTaskCompletedEvent { UserTaskId = p.Id }); } // Assert run3.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunCompleted); run3.RunLog.Should().NotBeNull().And.NotBeEmpty(); run3.RunLog.Where(l => l.Description == "MyVar: Jude Jacobs").Should().NotBeEmpty(); } finally { if (p != null) { ToDelete.Add(p.Id); } if (task != null) { ToDelete.Add(task.Id); } if (wf != null) { ToDelete.Add(wf.Id); } } } }
public void TestPromptActivityLowSecurityUser_Bug_27134() { Workflow wf = null; PromptUserTask p = null; try { // Arrange var dummyPerson = Entity.Create <Person>(); dummyPerson.Name = "Dummy Person" + DateTime.Now + Rand.Next(); dummyPerson.FirstName = "Dummy"; dummyPerson.LastName = "Dummy"; dummyPerson.Save(); var dummyAccount = Entity.Create <UserAccount>(); dummyAccount.Name = "Dummy" + DateTime.Now + Rand.Next(); dummyAccount.AccountHolder = dummyPerson; dummyAccount.Save(); wf = Entity.Create <Workflow>(); wf.Name = "Test User Input Workflow" + DateTime.Now + Rand.Next(); //wf.WorkflowRunAsOwner = true; //wf.SecurityOwner = dummyAccount; wf.AddWfExitPoint("Test User Input Workflow Exit Point", true); wf.AddInput <ResourceArgument>("input", Resource.Resource_Type); var act = Entity.Create <PromptUserActivity>(); act.Name = "Test User Input" + DateTime.Now + Rand.Next(); act.PromptForArguments.Add(new ActivityPrompt { Name = "input", ActivityPromptArgument = wf.InputArguments.First() }); var actAs = act.Cast <WfActivity>(); wf.AddActivity(actAs); wf.AddEntityExpressionToInputArgument(actAs, "For Person", dummyPerson); wf.Save(); // Act WorkflowRun run; using (new WorkflowRunContext { RunTriggersInCurrentThread = true }) { run = RunWorkflow(wf); } // Assert run.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused); run.PendingActivity.Should().NotBeNull(); run.PendingActivity.Name.Should().Be(act.Name); run.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1); var task = run.TaskWithinWorkflowRun.FirstOrDefault(); task.Should().NotBeNull(); using (new SetUser(dummyAccount)) { p = Entity.Get <PromptUserTask>(task.Id); p.Should().NotBeNull(); p.PromptForTaskArguments.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1); var arg = p.PromptForTaskArguments.First(); arg.ActivityPromptArgument.Should().NotBeNull(); arg.ActivityPromptArgument.Name.Should().Be("input"); } } finally { if (p != null) { ToDelete.Add(p.Id); } if (wf != null) { ToDelete.Add(wf.Id); } } }