private async Task <WorkflowTriggersContainer> GetWorkflowEventTriggersForNewArtifactEventInternal(int userId,
                                                                                                           IEnumerable <int> artifactIds,
                                                                                                           int revisionId,
                                                                                                           bool addDrafts)
        {
            var param = new DynamicParameters();

            param.Add("@userId", userId);
            var artifactIdsTable = SqlConnectionWrapper.ToDataTable(artifactIds);

            param.Add("@artifactIds", artifactIdsTable);
            param.Add("@revisionId", revisionId);
            param.Add("@addDrafts", addDrafts);
            var newArtifactEvents = (await
                                     ConnectionWrapper.QueryAsync <SqlWorkflowNewArtifactEvent>("GetWorkflowEventTriggersForNewArtifact",
                                                                                                param,
                                                                                                commandType: CommandType.StoredProcedure)).ToList();
            var eventTriggers = new WorkflowEventTriggers();

            newArtifactEvents.Where(n => n != null).ForEach(n =>
            {
                eventTriggers.AddRange(ToWorkflowTriggers(SerializationHelper.FromXml <XmlWorkflowEventTriggers>(n.Triggers), userId));
            });
            return(GetWorkflowTriggersContainer(eventTriggers));
        }
        private WorkflowEventTriggers ToWorkflowTriggers(XmlWorkflowEventTriggers xmlWorkflowEventTriggers, int currentUserId)
        {
            WorkflowEventTriggers triggers = new WorkflowEventTriggers();

            if (xmlWorkflowEventTriggers == null || xmlWorkflowEventTriggers.Triggers == null)
            {
                return(triggers);
            }
            triggers.AddRange(xmlWorkflowEventTriggers.Triggers.Select(xmlWorkflowEventTrigger => new WorkflowEventTrigger
            {
                Name      = xmlWorkflowEventTrigger.Name,
                Condition = new WorkflowEventCondition(),
                Action    = GenerateAction(xmlWorkflowEventTrigger.Action, currentUserId)
            }));
            return(triggers);
        }
        public async Task <ExecutionParameters> BuildTriggerExecutionParameters(
            int userId,
            VersionControlArtifactInfo artifactInfo,
            WorkflowEventTriggers triggers,
            IDbTransaction transaction = null)
        {
            if (triggers.IsEmpty())
            {
                return(null);
            }
            var artifactId = artifactInfo.Id;
            var isArtifactReadOnlyReuse = await _stateChangeExecutorRepositories.ReuseRepository.DoItemsContainReadonlyReuse(new[] { artifactId }, transaction);

            ItemTypeReuseTemplate reuseTemplate = null;
            var artifactId2StandardTypeId       = await _stateChangeExecutorRepositories.ReuseRepository.GetStandardTypeIdsForArtifactsIdsAsync(new HashSet <int> {
                artifactId
            });

            var instanceItemTypeId = artifactId2StandardTypeId[artifactId].InstanceTypeId;

            if (instanceItemTypeId == null)
            {
                throw new BadRequestException("Artifact is not a standard artifact type");
            }
            if (isArtifactReadOnlyReuse.ContainsKey(artifactId) && isArtifactReadOnlyReuse[artifactId])
            {
                reuseTemplate = await LoadReuseSettings(instanceItemTypeId.Value);
            }
            var customItemTypeToPropertiesMap = await LoadCustomPropertyInformation(new[] { instanceItemTypeId.Value }, triggers, artifactInfo.ProjectId, userId, artifactId);

            var propertyTypes = new List <WorkflowPropertyType>();

            if (customItemTypeToPropertiesMap.ContainsKey(artifactInfo.ItemTypeId))
            {
                propertyTypes = customItemTypeToPropertiesMap[artifactInfo.ItemTypeId];
            }
            var usersAndGroups = await LoadUsersAndGroups(triggers);

            return(new ExecutionParameters(
                       userId,
                       artifactInfo,
                       reuseTemplate,
                       propertyTypes,
                       _stateChangeExecutorRepositories.SaveArtifactRepository,
                       transaction,
                       new ValidationContext(usersAndGroups.Item1, usersAndGroups.Item2)));
        }
        private static WorkflowTriggersContainer GetWorkflowTriggersContainer(WorkflowEventTriggers eventTriggers)
        {
            var workflowTriggersContainer = new WorkflowTriggersContainer();

            foreach (var workflowEventTrigger in eventTriggers.Where(t => t?.Action != null))
            {
                if (workflowEventTrigger.Action is IWorkflowEventSynchronousAction)
                {
                    workflowTriggersContainer.SynchronousTriggers.Add(workflowEventTrigger);
                }
                else if (workflowEventTrigger.Action is IWorkflowEventASynchronousAction)
                {
                    workflowTriggersContainer.AsynchronousTriggers.Add(workflowEventTrigger);
                }
            }
            return(workflowTriggersContainer);
        }
        private async Task <Dictionary <int, List <WorkflowPropertyType> > > LoadCustomPropertyInformation(
            IEnumerable <int> instanceItemTypeIds,
            WorkflowEventTriggers triggers,
            int projectId,
            int userId,
            int artifactId)
        {
            var propertyChangeActions = triggers.Select(t => t.Action).OfType <PropertyChangeAction>().ToList();

            if (propertyChangeActions.Count == 0)
            {
                return(new Dictionary <int, List <WorkflowPropertyType> >());
            }

            var instancePropertyTypeIds = propertyChangeActions.Select(b => b.InstancePropertyTypeId);

            return(await _stateChangeExecutorRepositories.WorkflowRepository.GetCustomItemTypeToPropertiesMap(userId, artifactId, projectId, instanceItemTypeIds, instancePropertyTypeIds));
        }
Exemple #6
0
 public void TestInitialize()
 {
     _userId                         = 0;
     _revisionId                     = 0;
     _userName                       = "";
     _transactionId                  = 123;
     _workflowEventTriggers          = new WorkflowEventTriggers();
     _baseArtifactVersionControlInfo = new WorkflowMessageArtifactInfo();
     _projectName                    = "";
     _modifiedProperties             = new Dictionary <int, IList <Property> >();
     _currentState                   = new WorkflowState();
     _artifactUrl                    = "";
     _baseUrl                        = "";
     _ancestorArtifactTypeIds        = new int[] { };
     _mockUsersRepository            = new Mock <IUsersRepository>(MockBehavior.Strict);
     _mockServiceLogRepository       = new Mock <IServiceLogRepository>(MockBehavior.Strict);
     _mockWebhooksRepository         = new Mock <IWebhooksRepository>(MockBehavior.Strict);
     _mockProjectMetaRepository      = new Mock <IProjectMetaRepository>(MockBehavior.Strict);
 }
Exemple #7
0
        public async Task BuildTriggerExecutionParameters_WhenValid_ReturnsExecutionParameters()
        {
            // Arrange
            var artifactId = 1;
            var artifactStandardItemTypeId = 2;
            var artifactItemTypeId         = 3;
            var artifactInfo = new VersionControlArtifactInfo()
            {
                Id         = artifactId,
                ItemTypeId = artifactItemTypeId
            };
            var triggers = new WorkflowEventTriggers();

            triggers.Add(new WorkflowEventTrigger());
            var sqlItemTypeInfo = new SqlItemTypeInfo()
            {
                InstanceTypeId = artifactStandardItemTypeId
            };
            var isArtifactReadonlyReuseDictionary = new Dictionary <int, bool>()
            {
                { artifactId, false }
            };
            var artifactStandardItemTypeDictionary = new Dictionary <int, SqlItemTypeInfo>()
            {
                { artifactId, sqlItemTypeInfo }
            };

            _reuseRepository.Setup(
                r => r.DoItemsContainReadonlyReuse(It.IsAny <IEnumerable <int> >(), It.IsAny <IDbTransaction>()))
            .ReturnsAsync(isArtifactReadonlyReuseDictionary);
            _reuseRepository.Setup(
                r => r.GetStandardTypeIdsForArtifactsIdsAsync(It.IsAny <ISet <int> >()))
            .ReturnsAsync(artifactStandardItemTypeDictionary);

            var result =
                await
                _stateChangeExecutorHelper.BuildTriggerExecutionParameters(1, artifactInfo, triggers,
                                                                           null);

            // Assert
            Assert.IsNotNull(result);
        }
Exemple #8
0
        public static async Task <IList <IWorkflowMessage> > GenerateMessages(int userId,
                                                                              int revisionId,
                                                                              string userName,
                                                                              long transactionId,
                                                                              WorkflowEventTriggers postOpTriggers,
                                                                              IBaseArtifactVersionControlInfo artifactInfo,
                                                                              string projectName,
                                                                              IDictionary <int, IList <Property> > modifiedProperties,
                                                                              WorkflowState currentState,
                                                                              string artifactUrl,
                                                                              string baseUrl,
                                                                              IEnumerable <int> ancestorArtifactTypeIds,
                                                                              IUsersRepository usersRepository,
                                                                              IServiceLogRepository serviceLogRepository,
                                                                              IWebhooksRepository webhooksRepository,
                                                                              IProjectMetaRepository projectMetaRepository)
        {
            var resultMessages = new List <IWorkflowMessage>();
            var baseHostUri    = baseUrl ?? ServerUriHelper.GetBaseHostUri()?.ToString();

            foreach (var workflowEventTrigger in postOpTriggers)
            {
                if (workflowEventTrigger?.Action == null)
                {
                    continue;
                }
                switch (workflowEventTrigger.ActionType)
                {
                case MessageActionType.Notification:
                    var notificationAction = workflowEventTrigger.Action as EmailNotificationAction;
                    if (notificationAction == null)
                    {
                        continue;
                    }
                    var notificationMessage = await GetNotificationMessage(userId,
                                                                           revisionId,
                                                                           transactionId,
                                                                           artifactInfo,
                                                                           projectName,
                                                                           notificationAction,
                                                                           artifactUrl,
                                                                           baseHostUri,
                                                                           usersRepository);

                    if (notificationMessage == null)
                    {
                        await serviceLogRepository.LogInformation(LogSource, $"Skipping Email notification action for artifact {artifactInfo.Id}");

                        Log.Debug($" Skipping Email notification action for artifact {artifactInfo.Id}. Message: Notification.");
                        continue;
                    }
                    resultMessages.Add(notificationMessage);
                    break;

                case MessageActionType.GenerateChildren:
                    var generateChildrenAction = workflowEventTrigger.Action as GenerateChildrenAction;
                    if (generateChildrenAction == null)
                    {
                        continue;
                    }
                    var ancestors = new List <int>(ancestorArtifactTypeIds ?? new int[0]);
                    ancestors.Add(artifactInfo.ItemTypeId);
                    var generateChildrenMessage = new GenerateDescendantsMessage
                    {
                        TransactionId           = transactionId,
                        ChildCount              = generateChildrenAction.ChildCount.GetValueOrDefault(10),
                        DesiredArtifactTypeId   = generateChildrenAction.ArtifactTypeId,
                        ArtifactId              = artifactInfo.Id,
                        AncestorArtifactTypeIds = ancestors,
                        RevisionId              = revisionId,
                        UserId         = userId,
                        ProjectId      = artifactInfo.ProjectId,
                        UserName       = userName,
                        BaseHostUri    = baseHostUri,
                        ProjectName    = projectName,
                        TypePredefined = (int)artifactInfo.PredefinedType
                    };
                    resultMessages.Add(generateChildrenMessage);
                    break;

                case MessageActionType.GenerateTests:
                    var generateTestsAction = workflowEventTrigger.Action as GenerateTestCasesAction;
                    if (generateTestsAction == null || artifactInfo.PredefinedType != ItemTypePredefined.Process)
                    {
                        await serviceLogRepository.LogInformation(LogSource, $"Skipping GenerateTestCasesAction for artifact {artifactInfo.Id} as it is not a process");

                        Log.Debug($"Skipping GenerateTestCasesAction for artifact {artifactInfo.Id} as it is not a process. Message: Notification.");
                        continue;
                    }
                    var generateTestsMessage = new GenerateTestsMessage
                    {
                        TransactionId = transactionId,
                        ArtifactId    = artifactInfo.Id,
                        RevisionId    = revisionId,
                        UserId        = userId,
                        ProjectId     = artifactInfo.ProjectId,
                        UserName      = userName,
                        BaseHostUri   = baseHostUri,
                        ProjectName   = projectName
                    };
                    resultMessages.Add(generateTestsMessage);
                    break;

                case MessageActionType.GenerateUserStories:
                    var generateUserStories = workflowEventTrigger.Action as GenerateUserStoriesAction;
                    if (generateUserStories == null || artifactInfo.PredefinedType != ItemTypePredefined.Process)
                    {
                        await serviceLogRepository.LogInformation(LogSource, $"Skipping GenerateUserStories for artifact {artifactInfo.Id} as it is not a process");

                        Log.Debug($"Skipping GenerateUserStories for artifact {artifactInfo.Id} as it is not a process. Message: Notification.");
                        continue;
                    }
                    var generateUserStoriesMessage = new GenerateUserStoriesMessage
                    {
                        TransactionId = transactionId,
                        ArtifactId    = artifactInfo.Id,
                        RevisionId    = revisionId,
                        UserId        = userId,
                        ProjectId     = artifactInfo.ProjectId,
                        UserName      = userName,
                        BaseHostUri   = baseHostUri,
                        ProjectName   = projectName
                    };
                    resultMessages.Add(generateUserStoriesMessage);
                    break;

                case MessageActionType.Webhooks:
                    var webhookAction = workflowEventTrigger.Action as WebhookAction;
                    if (webhookAction == null)
                    {
                        continue;
                    }

                    var customTypes = await projectMetaRepository.GetCustomProjectTypesAsync(artifactInfo.ProjectId, userId);

                    var artifactType = customTypes.ArtifactTypes.FirstOrDefault(at => at.Id == artifactInfo.ItemTypeId);

                    var artifactPropertyInfos = await webhooksRepository.GetArtifactsWithPropertyValuesAsync(
                        userId,
                        new List <int> {
                        artifactInfo.Id
                    },
                        new List <int>
                    {
                        (int)PropertyTypePredefined.Name,
                        (int)PropertyTypePredefined.Description,
                        (int)PropertyTypePredefined.ID,
                        (int)PropertyTypePredefined.CreatedBy,
                        (int)PropertyTypePredefined.LastEditedOn,
                        (int)PropertyTypePredefined.LastEditedBy,
                        (int)PropertyTypePredefined.CreatedOn
                    },
                        artifactType.CustomPropertyTypeIds);

                    var webhookArtifactInfo = new WebhookArtifactInfo
                    {
                        Id          = Guid.NewGuid().ToString(),
                        EventType   = WebhookEventType,
                        PublisherId = WebhookPublisherId,
                        Scope       = new WebhookArtifactInfoScope
                        {
                            Type       = WebhookType,
                            WorkflowId = currentState.WorkflowId
                        },
                        Resource = new WebhookResource
                        {
                            Name                 = artifactInfo.Name,
                            ProjectId            = artifactInfo.ProjectId,
                            ParentId             = ((WorkflowMessageArtifactInfo)artifactInfo).ParentId,
                            ArtifactTypeId       = artifactInfo.ItemTypeId,
                            ArtifactTypeName     = artifactType?.Name,
                            BaseArtifactType     = artifactType?.PredefinedType?.ToString(),
                            ArtifactPropertyInfo =
                                await ConvertToWebhookPropertyInfo(artifactPropertyInfos, customTypes.PropertyTypes, usersRepository),
                            State = new WebhookStateInfo
                            {
                                Id         = currentState.Id,
                                Name       = currentState.Name,
                                WorkflowId = currentState.WorkflowId
                            },
                            Revision     = revisionId,
                            Version      = WebhookArtifactVersion,
                            Id           = artifactInfo.Id,
                            BlueprintUrl = string.Format($"{baseHostUri}?ArtifactId={artifactInfo.Id}"),
                            Link         = string.Format($"{baseHostUri}api/v1/projects/{artifactInfo.ProjectId}/artifacts/{artifactInfo.Id}")
                        }
                    };
                    var webhookMessage = await GetWebhookMessage(userId, revisionId, transactionId, webhookAction, webhooksRepository, webhookArtifactInfo);

                    if (webhookMessage == null)
                    {
                        await serviceLogRepository.LogInformation(LogSource, $"Skipping Webhook action for artifact {artifactInfo.Id}: {artifactInfo.Name}.");

                        continue;
                    }
                    resultMessages.Add(webhookMessage);
                    break;
                }
            }
            return(resultMessages);
        }
        private async Task <Tuple <IEnumerable <SqlUser>, IEnumerable <SqlGroup> > > LoadUsersAndGroups(WorkflowEventTriggers triggers)
        {
            var userGroups = triggers.Select(a => a.Action).OfType <PropertyChangeUserGroupsAction>().SelectMany(b => b.UserGroups).ToList();
            var userIds    = userGroups.Where(u => !u.IsGroup.GetValueOrDefault(false) && u.Id.HasValue).Select(u => u.Id.Value).ToHashSet();
            var groupIds   = userGroups.Where(u => u.IsGroup.GetValueOrDefault(false) && u.Id.HasValue).Select(u => u.Id.Value).ToHashSet();

            var users = new List <SqlUser>();

            if (userIds.Any())
            {
                users.AddRange(await _stateChangeExecutorRepositories.UsersRepository.GetExistingUsersByIdsAsync(userIds));
            }
            var groups = new List <SqlGroup>();

            if (groupIds.Any())
            {
                groups.AddRange(
                    await _stateChangeExecutorRepositories.UsersRepository.GetExistingGroupsByIds(groupIds, false));
            }

            return(new Tuple <IEnumerable <SqlUser>, IEnumerable <SqlGroup> >(users, groups));
        }