Beispiel #1
0
        private void ValidateExpressions(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("WorkflowImplementation.ValidateExpressions"))
            {
                // Validate the Expressions
                // - all expressions have a target argument
                // - no more than one expression can target an argument

                var allExp = _activityInstanceAsWf.ContainedActivities.SelectMany(a => a.ExpressionMap.Select(e => new { Activity = a, Expression = e }));
                allExp = allExp.Union(ActivityInstance.ExpressionMap.Select(e => new { Activity = ActivityInstance, Expression = e })).ToList();

                foreach (var exp in allExp)
                {
                    var e = exp.Expression;
                    if (e.ArgumentToPopulate == null)
                    {
                        var s = string.Format("Warning: Expression for \"{0}\" ({1}) missing argument to populate: expression name=\"{2}\" ({3}) value=\"{4}\".",
                                              exp.Activity != null ? exp.Activity.Name : "", exp.Activity != null ? exp.Activity.Id.ToString() : "",
                                              e.Name ?? "", e.Id, e.GetExpressionDisplayString());
                        EventLog.Application.WriteWarning(s);
                        //metadata.AddValidationError(s);
                    }
                }
            }
        }
Beispiel #2
0
        private void ValidateTransitions(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("WorkflowImplementation.ValidateTransitions"))
            {
                foreach (var tran in metadata.AllTransitions)
                {
                    if (tran.FromActivity == null || tran.FromExitPoint == null || tran.ToActivity == null)
                    {
                        metadata.AddValidationError(
                            string.Format("Workflow '{0}' does not have one of its transitions ({1}) fully described. It must have a from activity and exit point and a destination. "
                                          + "From {2} {3} to {4}",
                                          ActivityInstance.Name, tran.Id,
                                          tran.FromActivity != null ? tran.FromActivity.Name ?? tran.FromActivity.Id.ToString() : "null",
                                          tran.FromExitPoint != null ? tran.FromExitPoint.Name ?? tran.FromExitPoint.Id.ToString() : "null",
                                          tran.ToActivity != null ? tran.ToActivity.Name ?? tran.FromActivity.Id.ToString() : "null"
                                          ));
                    }

                    // validate that all transitions point to children of the workflow
                    if (tran.ToActivity != null && (tran.ToActivity.ContainingWorkflow == null || tran.ToActivity.ContainingWorkflow.Id != _activityInstanceAsWf.Id))
                    {
                        metadata.AddValidationError(string.Format("Activity '{0}' is not a child of the workflow but is part of a transition", tran.FromActivity.Name));
                    }
                }
            }
        }
        /// <summary>
        /// Validate the activity, adding any validation errors to the metadata
        /// </summary>
        /// <param name="metadata"></param>
        public virtual void Validate(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("ActivityImplementationBase.Validate"))
            {
                var manditoryArgs = ActivityInstance.GetInputArguments().Where(arg => arg.ArgumentIsMandatory ?? false);

                // we can't validate inputs unless we are part of a workflow
                if (ActivityInstance.ContainingWorkflow == null)
                {
                    return;
                }

                foreach (var manditoryArg in manditoryArgs)
                {
                    var expression = metadata.GetPopulatedBy(ActivityInstance, manditoryArg);

                    if (expression == null)
                    {
                        metadata.AddValidationError(
                            string.Format(
                                "Mandatory arguments must be given a value. Activity: '{0}'  Argument: '{1}'",
                                ActivityInstance.Name, manditoryArg.Name));
                    }
                }
            }
        }
Beispiel #4
0
 public RunState(WorkflowMetadata metaData, WorkflowRun workflowRun, RequestContextData effectiveSecurityContext)
     : base(metaData, workflowRun, effectiveSecurityContext)
 {
     ownerAccountRuntimeArgName     = Entity.GetName(new EntityRef("workflowOwnerAccount").Id);
     triggeringUserRuntimeArgName   = Entity.GetName(new EntityRef("triggeringUserAccount").Id);
     triggeringPersonRuntimeArgName = Entity.GetName(new EntityRef("triggeringPerson").Id);
 }
Beispiel #5
0
        /// <summary>
        /// Get the request context this workflow will be running as, taking into account triggering user and owner.
        /// </summary>
        private RequestContextData GetEffectiveSecurityContext(WorkflowRun run, WorkflowMetadata metaData)
        {
            var effectiveUser  = GetEffectiveUser(run, metaData);
            var triggeringUser = GetTriggeringUser(run);

            // Error! The caller will deal with the missing info. We can't throw becasue RunState is needed for the error reporting
            if (effectiveUser == null)
            {
                return(null);
            }

            if (metaData.WfRunAsOwner && metaData.WfSecurityOwner == null)
            {
                return(null);
            }

            var identityInfo = new IdentityInfo(effectiveUser.Id, effectiveUser.Name);


            var context = RequestContext.GetContext();

            var effectiveSecurityContext = new RequestContextData(context);

            effectiveSecurityContext.Identity = identityInfo;

            // If we are running as someone other than the triggerer, set the secondary identity to the triggerer.
            // NOTE: This could potentially cause a problem in the case where a wf triggering another wf scenario.
            // It's possible that the user will see stale data. The risk should be quite low.
            if (triggeringUser != null && triggeringUser.Id != effectiveUser.Id)
            {
                effectiveSecurityContext.SecondaryIdentity = new IdentityInfo(triggeringUser.Id, triggeringUser.Name);
            }

            return(effectiveSecurityContext);
        }
Beispiel #6
0
        private UserAccount GetEffectiveUser(WorkflowRun run, WorkflowMetadata metaData)
        {
            if (metaData != null && metaData.WfRunAsOwner)
            {
                return(metaData.WfSecurityOwner);
            }

            return(GetTriggeringUser(run));
        }
Beispiel #7
0
        public override void Validate(WorkflowMetadata metadata)
        {
            base.Validate(metadata);

            var activityAs = ActivityInstance.Cast <AssignToVariable>();

            if (activityAs.TargetVariable == null)
            {
                metadata.AddValidationError(string.Format("Variable has not been assigned. Activity: '{0}'", activityAs.Name));
            }
        }
Beispiel #8
0
        public RunStateBase(WorkflowMetadata metaData, WorkflowRun _workflowRun, RequestContextData effectiveSecurityContext)
            : this(metaData)
        {
            WorkflowInvoker = new WorkflowInvoker();
            WorkflowRun     = _workflowRun;

            StepsTakenInSession      = 0;
            EffectiveSecurityContext = effectiveSecurityContext;
            ExitPointId     = _workflowRun.WorkflowRunExitPoint;
            HasTimeout      = _workflowRun.HasTimeout ?? false;
            PendingActivity = _workflowRun.PendingActivity;
            RunStatus       = _workflowRun.WorkflowRunStatus_Enum;
            CompletedAt     = _workflowRun.RunCompletedAt;
        }
        public override void Validate(WorkflowMetadata metadata)
        {
            base.Validate(metadata);

            var workflowToProxy = ActivityInstance.As <WorkflowProxy>().WorkflowToProxy;

            if (workflowToProxy == null)
            {
                metadata.AddValidationError("Workflow to run has not been set.");
            }

            //
            // The proxy workflow will be validated separately
            //
        }
Beispiel #10
0
        private void ValidateWorkflowVariables(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("WorkflowImplementation.ValidateWorkflowVariables"))
            {
                // Validate workflow variables
                var inputArgumentsNames = _activityInstanceAsWf.InputArguments.Select(arg => arg.Name);

                foreach (var wfVar in _activityInstanceAsWf.Variables)
                {
                    if (inputArgumentsNames.Contains(wfVar.Name))
                    {
                        metadata.AddValidationError(string.Format("Name of variable '{0}' clashed with the input argument of the same name.", wfVar.Name));
                    }
                }
            }
        }
Beispiel #11
0
        public override void Validate(WorkflowMetadata metadata)
        {
            base.Validate(metadata);

            var activityInstanceAs = ActivityInstance.Cast <ForEachResource>();

            var terminationsCount =
                activityInstanceAs.ContainingWorkflow.Terminations.Count(t => t.FromActivity.Id == activityInstanceAs.Id);

            var transitionsCount = activityInstanceAs.ContainingWorkflow.Transitions.Count(t => t.FromActivity.Id == activityInstanceAs.Id);

            if (transitionsCount + terminationsCount != 2)
            {
                metadata.AddValidationError(string.Format("Every 'For Each' activity must have a Loop and a Finish transition. Activity: '{0}'", activityInstanceAs.Name));
            }
        }
Beispiel #12
0
        /// <summary>
        /// Create a run state
        /// </summary>
        /// <returns>A run state - note the security information will be missing if it has been set incorrectly in the workflow</returns>
        public IRunState CreateRunState(WorkflowMetadata metaData, WorkflowRun workflowRun)
        {
            using (Profiler.Measure("DefaultRunStateFactory.CreateRunState"))
            {
                var run = workflowRun;

                if (!run.IsTemporaryId)
                {
                    run = run.AsWritable <WorkflowRun>();
                }

                //var effectiveUser = GetEffectiveUser(run, metaData);
                var effectiveSecurityContext = GetEffectiveSecurityContext(run, metaData);

                return(new RunState(metaData, run, effectiveSecurityContext));
            }
        }
Beispiel #13
0
 private void ValidateTerminations(WorkflowMetadata metadata)
 {
     using (Profiler.Measure("WorkflowImplementation.ValidateTerminations"))
     {
         foreach (var term in _activityInstanceAsWf.Terminations)
         {
             if (term.FromActivity == null || term.FromExitPoint == null || term.WorkflowExitPoint == null)
             {
                 metadata.AddValidationError(
                     string.Format(
                         "Workflow '{0}' does not have one of its terminations fully described. It must have a from activity and exit point and a workflow exit point. From '{1}':'{2}'  To:'{3}'",
                         ActivityInstance.Name,
                         term.FromActivity != null ? term.FromActivity.Name ?? "Unnamed activity" : "Activity not specified",
                         term.FromExitPoint != null ? term.FromExitPoint.Name ?? "Unnamed exit" : "Exit not specified",
                         term.WorkflowExitPoint != null ? term.WorkflowExitPoint.Name ?? "Unnamed workflow exit" : "Exit not specified"));
             }
         }
     }
 }
        /// <summary>
        /// Validate that the reply workflow is marked as RunAsOwner.
        /// </summary>
        /// <param name="metadata"></param>
        public override void Validate(WorkflowMetadata metadata)
        {
            base.Validate(metadata);

            var activityAs = ActivityInstance.Cast <NotifyActivity>();

            foreach (var entry in activityAs.NReplyMap)
            {
                if (String.IsNullOrWhiteSpace(entry.Name))
                {
                    metadata.AddValidationError($"An all entries in the reply mapping must contain a value: '{activityAs.Name}'");
                }
                else if (entry.RmeWorkflow == null)
                {
                    metadata.AddValidationError($"Mapping entry '{entry.Name}' does not point to a workflow: '{activityAs.Name}'");
                }
                else if (entry.RmeWorkflow.WorkflowRunAsOwner != true)
                {
                    metadata.AddValidationError($"Mapping entry '{entry.Name}' points to a workflow that is not set to 'Run as owner': '{activityAs.Name}'");
                }
            }
        }
Beispiel #15
0
        private void ValidateTransitions2(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("WorkflowImplementation.ValidateTransitions2"))
            {
                //
                // Validate that all the transitions from the activities are in the Transitions list
                var comparer = new EntityIdComparer();

                var wfTransAndTerms = ((IEnumerable <IEntity>)_activityInstanceAsWf.Transitions).Union((IEnumerable <IEntity>)_activityInstanceAsWf.Terminations).ToList();

                using (Profiler.Measure("WorkflowImplementation.ValidateTransitions2.1"))
                {
                    foreach (var activity in _activityInstanceAsWf.ContainedActivities)
                    {
                        // validate that all the transitions are on the workflow

                        var missing = activity.ForwardTransitions.Except(wfTransAndTerms, comparer);

                        if (missing.Any())
                        {
                            metadata.AddValidationError(string.Format("Activity \"{0}\" has a transition that is not listed against the workflow.", activity.Name ?? "(Unnamed)"));
                        }


                        // validate that the transitions have a from exit point on the activity or its type
                        var exitPoints = metadata.GetExitpointsForActivity(activity.Id);
                        foreach (var tran in activity.ForwardTransitions)
                        {
                            if (!exitPoints.Contains(tran.FromExitPoint, comparer))
                            {
                                metadata.AddValidationError(
                                    string.Format("Activity \"{0}\" has a transition whose exit point is not from the origin activity.", activity.Name ?? "(Unnamed)"));
                            }
                        }
                    }
                }
            }
        }
Beispiel #16
0
 private RunStateBase(WorkflowMetadata metadata)
 {
     Metadata           = metadata;
     TimeTakenInSession = new System.Diagnostics.Stopwatch();
 }
Beispiel #17
0
        private IRunState CreateRunState(WorkflowMetadata metadata, WorkflowRun run)
        {
            var factory = Factory.Current.Resolve <IRunStateFactory>();

            return(factory.CreateRunState(metadata, run));
        }
Beispiel #18
0
        public override void Validate(WorkflowMetadata metadata)
        {
            using (Profiler.Measure("WorkflowImplementation.Validate"))
            {
                using (new SecurityBypassContext())
                {
                    base.Validate(metadata);

                    // validate first activity
                    if (_activityInstanceAsWf.FirstActivity == null)
                    {
                        metadata.AddValidationError("First Activity is missing.");
                    }

                    // ensure that all workflow variables are also in the expression parameters
                    foreach (var v in _activityInstanceAsWf.Variables)
                    {
                        if (_activityInstanceAsWf.ExpressionParameters.All(p => p.ArgumentInstanceArgument.Id != v.Id))
                        {
                            metadata.AddValidationError(string.Format("Variable '{0}' is missing from the expression parameter list.", v.Name));
                        }
                    }

                    // ensure the name, activity and argument are defined for the expression parameters
                    foreach (var param in _activityInstanceAsWf.ExpressionParameters)
                    {
                        if (param.Name == null)
                        {
                            metadata.AddValidationError(string.Format("Parameter '{0}' is missing a name.", param.Id));
                        }

                        if (param.ArgumentInstanceActivity == null || param.ArgumentInstanceArgument == null)
                        {
                            metadata.AddValidationError(string.Format("Parameter '{0}' is missing source information, must have both activity and argument defined.", param.Name));
                        }
                    }

                    ValidateExpressions(metadata);

                    ValidateWorkflowVariables(metadata);
                    ValidateTransitions(metadata);
                    ValidateTerminations(metadata);

                    ValidateTransitions2(metadata);


                    //
                    // validate first activity
                    //
                    if (_activityInstanceAsWf.FirstActivity == null)
                    {
                        metadata.AddValidationError("The workflow has no first activity.");
                    }

                    //
                    // Validate all the contained activities
                    foreach (var activityInstance in metadata.CachedInstances.Values)
                    {
                        if (activityInstance != this)
                        {
                            activityInstance.Validate(metadata);
                        }
                    }

                    //
                    // Ensure that all activities have unique names. (This ensures that activity outputs cannot have name clashes.)
                    var allNames   = _activityInstanceAsWf.ContainedActivities.Select(a => a.Name);
                    var duplicates = allNames.GroupBy(s => s).SelectMany(grp => grp.Skip(1));

                    if (duplicates.Count() > 0)
                    {
                        metadata.AddValidationError(string.Format("All activities in a workflow must have a unique name: {0}", string.Join(", ", duplicates)));
                    }
                }
            }
        }