Example #1
0
        /// <summary>
        /// Moves instance's process to nextElement id. Returns the instance together with process events.
        /// </summary>
        public ProcessStateChange ProcessNext(Instance instance, string nextElementId, ClaimsPrincipal userContext)
        {
            if (instance.Process != null)
            {
                try
                {
                    string validNextEmentId = CheckNextElementId(instance, nextElementId);

                    ProcessStateChange result = new ProcessStateChange
                    {
                        OldProcessState = new ProcessState()
                        {
                            Started     = instance.Process.Started,
                            CurrentTask = instance.Process.CurrentTask,
                            StartEvent  = instance.Process.StartEvent
                        }
                    };

                    result.Events          = MoveProcessToNext(instance, validNextEmentId, userContext);
                    result.NewProcessState = instance.Process;
                    return(result);
                }
                catch
                {
                    _logger.LogError($"Unable to get next for {instance.Id}");
                }
            }

            return(null);
        }
Example #2
0
        private void ProcessStateChangeHandler(ProcessStateChange obj)
        {
            try
            {
                var processChange = obj.Change;
                var name          = obj.Name;
                var process       = obj.Process;
                switch (processChange)
                {
                case ProcessChange.Started:
                    if (_config.Kernel.Contains(name))
                    {
                        ConfigProcess(process);
                        Kernel += process;
                    }

                    if (_config.Client.Contains(name))
                    {
                        ConfigProcess(process);
                        Client += process;
                    }

                    break;

                case ProcessChange.Stopped:
                    if (_config.Kernel.Contains(name))
                    {
                        Kernel += null !;
                    }
                    if (_config.Client.Contains(name))
                    {
                        Client += null !;
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (Kernel != null && Client != null)
                {
                    Status += Context.Loc().RequestString("uistatusstartet");
                }
                if (Kernel == null && Client == null)
                {
                    Status += Context.Loc().RequestString("uistatusstopped");
                }
            }
            catch (Exception e)
            {
                Status += "Fehler: " + e.Message;
            }
        }
Example #3
0
        /// <summary>
        /// Start process start and goto next. Returns
        /// </summary>
        public ProcessStateChange ProcessStartAndGotoNextTask(Instance instance, string proposedStartEvent, ClaimsPrincipal user)
        {
            _logger.LogInformation($"ProcessStartAndGotoNextTask for {instance.Id}");

            // start process
            ProcessStateChange startChange = ProcessStart(instance, proposedStartEvent, user);

            string nextValidElement = GetNextElement(instance.Process.StartEvent);

            // move next
            ProcessStateChange nextChange = ProcessNext(instance, nextValidElement, user);

            // consolidate events
            startChange.Events.AddRange(nextChange.Events);
            startChange.NewProcessState = nextChange.NewProcessState;

            return(startChange);
        }
Example #4
0
        public async Task <ActionResult <ProcessState> > StartProcess(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromRoute] int instanceOwnerPartyId,
            [FromRoute] Guid instanceGuid,
            [FromQuery] string startEvent = null)
        {
            Instance instance = null;

            try
            {
                instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid);

                if (instance.Process != null)
                {
                    return(Conflict($"Process is already started. Use next."));
                }

                string validStartElement = processHelper.GetValidStartEventOrError(startEvent, out ProcessError startEventError);
                if (startEventError != null)
                {
                    return(Conflict(startEventError.Text));
                }

                // trigger start event and goto next task
                ProcessStateChange processStateChange = _processService.ProcessStartAndGotoNextTask(instance, validStartElement, User);
                Instance           updatedInstance    = await UpdateInstanceAndDispatchEvents(instance, processStateChange);

                return(Ok(updatedInstance.Process));
            }
            catch (PlatformHttpException e)
            {
                return(HandlePlatformHttpException(e, $"Unable to start the process for instance {instance.Id} of {instance.AppId}"));
            }
            catch (Exception startException)
            {
                _logger.LogError($"Unable to start the process for instance {instance.Id} of {instance.AppId}. Due to {startException}");
                return(ExceptionResponse(startException, $"Unable to start the process for instance {instance.Id} of {instance.AppId}"));
            }
        }
Example #5
0
        /// <summary>
        /// Start process start and goto next. Returns
        /// </summary>
        public ProcessStateChange ProcessStartAndGotoNextTask(Instance instance, string proposedStartEvent, ClaimsPrincipal user)
        {
            _logger.LogInformation($"ProcessStartAndGotoNextTask for {instance.Id}");

            // start process
            ProcessStateChange startChange = ProcessStart(instance, proposedStartEvent, user);
            InstanceEvent      startEvent  = CopyInstanceEventValue(startChange.Events.First());

            // move next
            string             nextValidElement = GetNextElement(instance.Process.StartEvent);
            ProcessStateChange nextChange       = ProcessNext(instance, nextValidElement, user);
            InstanceEvent      goToNextEvent    = CopyInstanceEventValue(nextChange.Events.First());

            ProcessStateChange processStateChange = new ProcessStateChange
            {
                OldProcessState = startChange.OldProcessState,
                NewProcessState = nextChange.NewProcessState,
                Events          = new List <InstanceEvent> {
                    startEvent, goToNextEvent
                }
            };

            return(processStateChange);
        }
Example #6
0
        public async Task <ActionResult <ProcessState> > CompleteProcess(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromRoute] int instanceOwnerPartyId,
            [FromRoute] Guid instanceGuid)
        {
            Instance instance = null;

            try
            {
                instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid);
            }
            catch (PlatformHttpException e)
            {
                return(HandlePlatformHttpException(e, "Could not complete process."));
            }

            if (instance.Process == null)
            {
                return(Conflict($"Process is not started. Use start!"));
            }
            else
            {
                if (instance.Process.Ended.HasValue)
                {
                    return(Conflict($"Process is ended. It cannot be restarted."));
                }
            }

            string currentTaskId = instance.Process.CurrentTask?.ElementId ?? instance.Process.StartEvent;

            if (currentTaskId == null)
            {
                return(Conflict($"Instance does not have valid currentTask"));
            }

            // do next until end event is reached or task cannot be completed.
            int counter = 0;

            do
            {
                string altinnTaskType = instance.Process.CurrentTask?.AltinnTaskType;

                bool authorized = await AuthorizeAction(altinnTaskType, org, app, instanceOwnerPartyId, instanceGuid);

                if (!authorized)
                {
                    return(Forbid());
                }

                if (!await CanTaskBeEnded(instance, currentTaskId))
                {
                    return(Conflict($"Instance is not valid for task {currentTaskId}. Automatic completion of process is stopped"));
                }

                List <string> nextElements = processHelper.Process.NextElements(currentTaskId);

                if (nextElements.Count > 1)
                {
                    return(Conflict($"Cannot complete process. Multiple outgoing sequence flows detected from task {currentTaskId}. Please select manually among {nextElements}"));
                }

                string nextElement = nextElements.First();

                try
                {
                    ProcessStateChange nextResult = _processService.ProcessNext(instance, nextElement, User);

                    if (nextResult != null)
                    {
                        instance = await UpdateInstanceAndDispatchEvents(instance, nextResult);

                        currentTaskId = instance.Process.CurrentTask?.ElementId;
                    }
                    else
                    {
                        return(Conflict($"Cannot complete process. Unable to move to next element {nextElement}"));
                    }
                }
                catch (Exception ex)
                {
                    return(ExceptionResponse(ex, "Complete process failed."));
                }

                counter++;
            }while (instance.Process.EndEvent == null || counter > MAX_ITERATIONS_ALLOWED);

            if (counter > MAX_ITERATIONS_ALLOWED)
            {
                _logger.LogError($"More than {counter} iterations detected in process. Possible loop. Fix app {org}/{app}'s process definition!");
                return(StatusCode(500, $"More than {counter} iterations detected in process. Possible loop. Fix app process definition!"));
            }

            return(Ok(instance.Process));
        }
Example #7
0
        public async Task <ActionResult <ProcessState> > NextElement(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromRoute] int instanceOwnerPartyId,
            [FromRoute] Guid instanceGuid,
            [FromQuery] string elementId = null)
        {
            try
            {
                Instance instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid);

                if (instance.Process == null)
                {
                    return(Conflict($"Process is not started. Use start!"));
                }

                if (instance.Process.Ended.HasValue)
                {
                    return(Conflict($"Process is ended."));
                }

                if (!string.IsNullOrEmpty(elementId))
                {
                    ElementInfo elemInfo = processHelper.Process.GetElementInfo(elementId);
                    if (elemInfo == null)
                    {
                        return(BadRequest($"Requested element id {elementId} is not found in process definition"));
                    }
                }

                string altinnTaskType = instance.Process.CurrentTask?.AltinnTaskType;

                if (altinnTaskType == null)
                {
                    return(Conflict($"Instance does not have current altinn task type information!"));
                }

                bool authorized = await AuthorizeAction(altinnTaskType, org, app, instanceOwnerPartyId, instanceGuid);

                if (!authorized)
                {
                    return(Forbid());
                }

                string currentElementId = instance.Process.CurrentTask?.ElementId;

                if (currentElementId == null)
                {
                    return(Conflict($"Instance does not have current task information!"));
                }

                if (currentElementId.Equals(elementId))
                {
                    return(Conflict($"Requested process element {elementId} is same as instance's current task. Cannot change process."));
                }

                string nextElement = processHelper.GetValidNextElementOrError(currentElementId, elementId, out ProcessError nextElementError);
                if (nextElementError != null)
                {
                    return(Conflict(nextElementError.Text));
                }

                if (await CanTaskBeEnded(instance, currentElementId))
                {
                    ProcessStateChange nextResult = _processService.ProcessNext(instance, nextElement, User);
                    if (nextResult != null)
                    {
                        Instance changedInstance = await UpdateInstanceAndDispatchEvents(instance, nextResult);

                        return(Ok(changedInstance.Process));
                    }
                }
                return(Conflict($"Cannot complete/close current task {currentElementId}. The data element(s) assigned to the task are not valid!"));
            }
            catch (PlatformHttpException e)
            {
                return(HandlePlatformHttpException(e, "Process next failed."));
            }
            catch (Exception exception)
            {
                return(ExceptionResponse(exception, "Process next failed."));
            }
        }
Example #8
0
        private async Task <Instance> UpdateInstanceAndDispatchEvents(Instance instance, ProcessStateChange processStateChange)
        {
            await NotifyAppAboutEvents(_altinnApp, instance, processStateChange.Events);

            // need to update the instance process and then the instance in case appbase has changed it, e.g. endEvent sets status.archived
            Instance instanceWithUpdatedProcess = await _instanceService.UpdateProcess(instance);

            Instance updatedInstance = await _instanceService.UpdateInstance(instanceWithUpdatedProcess);

            await _processService.DispatchProcessEventsToStorage(updatedInstance, processStateChange.Events);

            // remember to get the instance anew since AppBase can have updated a data element or stored something in the database.
            updatedInstance = await _instanceService.GetInstance(updatedInstance);

            return(updatedInstance);
        }