Beispiel #1
0
        private static async Task <IWorkflowMessage> GetNotificationMessage(int userId,
                                                                            int revisionId,
                                                                            long transactionId,
                                                                            IBaseArtifactVersionControlInfo artifactInfo,
                                                                            string projectName,
                                                                            EmailNotificationAction notificationAction,
                                                                            string artifactUrl,
                                                                            string blueprintUrl,
                                                                            IUsersRepository usersRepository)
        {
            string messageHeader   = I18NHelper.FormatInvariant("You are being notified because artifact with Id: {0} has been created.", artifactInfo.Id);
            var    artifactPartUrl = artifactUrl ?? ServerUriHelper.GetArtifactUrl(artifactInfo.Id, true);

            if (artifactPartUrl == null)
            {
                return(null);
            }
            var baseUrl = blueprintUrl ?? ServerUriHelper.GetBaseHostUri()?.ToString();
            var emails  = await GetEmailValues(revisionId, artifactInfo.Id, notificationAction, usersRepository);

            var notificationMessage = new NotificationMessage
            {
                TransactionId          = transactionId,
                ArtifactName           = artifactInfo.Name,
                ProjectName            = projectName,
                Subject                = I18NHelper.FormatInvariant("Artifact {0} has been created.", artifactInfo.Id),
                From                   = notificationAction.FromDisplayName,
                To                     = emails,
                Message                = notificationAction.Message,
                RevisionId             = revisionId,
                UserId                 = userId,
                ArtifactTypeId         = artifactInfo.ItemTypeId,
                ArtifactId             = artifactInfo.Id,
                ArtifactUrl            = artifactPartUrl,
                ArtifactTypePredefined = (int)artifactInfo.PredefinedType,
                ProjectId              = artifactInfo.ProjectId,
                Header                 = messageHeader,
                BlueprintUrl           = baseUrl
            };

            return(notificationMessage);
        }
        private static IWorkflowMessage GetPublishedMessage(int userId, int revisionId, long transactionId, IBaseArtifactVersionControlInfo artifactInfo, IDictionary <int, IList <Property> > modifiedProperties)
        {
            var message = new ArtifactsPublishedMessage
            {
                TransactionId = transactionId,
                UserId        = userId,
                RevisionId    = revisionId
            };
            var artifacts = new List <PublishedArtifactInformation>();
            var artifact  = new PublishedArtifactInformation
            {
                Id                   = artifactInfo.Id,
                Name                 = artifactInfo.Name,
                Predefined           = (int)artifactInfo.PredefinedType,
                IsFirstTimePublished = false, // State change always occurs on published artifacts
                ProjectId            = artifactInfo.ProjectId,
                Url                  = ServerUriHelper.GetArtifactUrl(artifactInfo.Id, true),
                ModifiedProperties   = new List <PublishedPropertyInformation>()
            };

            IList <Property> artifactModifiedProperties;

            if (modifiedProperties?.Count > 0 && modifiedProperties.TryGetValue(artifactInfo.Id, out artifactModifiedProperties) && artifactModifiedProperties?.Count > 0)
            {
                artifact.ModifiedProperties.AddRange(artifactModifiedProperties.Select(p => new PublishedPropertyInformation
                {
                    TypeId         = p.PropertyTypeId,
                    PredefinedType = (int)p.Predefined
                }));
                // Only add artifact to list if there is a list of modified properties
                artifacts.Add(artifact);
            }

            message.Artifacts = artifacts;
            return(message);
        }
Beispiel #3
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 static async Task ProcessCustomPropertyChange(TenantInformation tenant,
                                                              ArtifactsPublishedMessage message,
                                                              IArtifactsPublishedRepository repository,
                                                              List <EmailNotificationAction> notifications,
                                                              HashSet <int> modifiedCustomPropertiesSet,
                                                              SqlWorkFlowStateInformation currentStateInfo,
                                                              List <PublishedArtifactInformation> updatedArtifacts,
                                                              int artifactId,
                                                              Dictionary <int, SqlWorkFlowStateInformation> workflowStates,
                                                              List <SqlProject> projects,
                                                              Dictionary <int, List <IWorkflowMessage> > notificationMessages)
        {
            if (modifiedCustomPropertiesSet.Count == 0)
            {
                return;
            }
            ////Dictionary<int, List<int>> instancePropertyTypeIds
            var instancePropertyTypeIds = await repository.GetInstancePropertyTypeIdsMap(modifiedCustomPropertiesSet);

            Logger.Log(
                $"{instancePropertyTypeIds.Count} instance property type IDs found: {string.Join(", ", instancePropertyTypeIds.Select(k => k.Key))}",
                message, tenant, LogLevel.Debug);

            foreach (var notificationAction in notifications)
            {
                Logger.Log("Processing notification action", message, tenant, LogLevel.Debug);

                if (!notificationAction.EventPropertyTypeId.HasValue)
                {
                    continue;
                }

                int eventPropertyTypeId = notificationAction.EventPropertyTypeId.Value;
                if (!instancePropertyTypeIds.ContainsKey(eventPropertyTypeId))
                {
                    Logger.Log(
                        $"The property type ID {notificationAction.EventPropertyTypeId} was not found in the dictionary of instance property type IDs.",
                        message, tenant, LogLevel.Debug);
                    continue;
                }

                List <int> propertyTypeIds;
                if (!instancePropertyTypeIds.TryGetValue(eventPropertyTypeId, out propertyTypeIds) || propertyTypeIds.IsEmpty())
                {
                    Logger.Log(
                        $"The property type ID {notificationAction.EventPropertyTypeId} was not found in the dictionary of instance property type IDs.",
                        message, tenant, LogLevel.Debug);
                    continue;
                }

                if (notificationAction.ConditionalStateId.HasValue &&
                    (currentStateInfo == null ||
                     currentStateInfo.WorkflowStateId != notificationAction.ConditionalStateId.Value))
                {
                    // The conditional state id is present, but either the current state info is not present or the current state is not same as conditional state
                    var currentStateId = currentStateInfo?.WorkflowStateId.ToString() ?? "none";
                    Logger.Log(
                        $"Conditional state ID {notificationAction.ConditionalStateId.Value} does not match current state ID: {currentStateId}",
                        message, tenant, LogLevel.Debug);
                    continue;
                }

                var artifact = updatedArtifacts.First(a => a.Id == artifactId);

                string messageHeader =
                    I18NHelper.FormatInvariant("You are being notified because artifact with Id: {0} has been updated.",
                                               artifactId);
                var artifactPartUrl = artifact.Url ?? ServerUriHelper.GetArtifactUrl(artifactId, true);
                var blueprintUrl    = artifact.BaseUrl ?? ServerUriHelper.GetBaseHostUri()?.ToString();
                var emails          = await WorkflowEventsMessagesHelper.GetEmailValues(message.RevisionId, artifactId,
                                                                                        notificationAction, repository.UsersRepository);

                var notificationMessage = new NotificationMessage
                {
                    TransactionId          = message.TransactionId,
                    ArtifactName           = workflowStates[artifactId].Name,
                    ProjectName            = projects.First(p => p.ItemId == artifact.ProjectId).Name,
                    Subject                = notificationAction.Subject,
                    From                   = notificationAction.FromDisplayName,
                    To                     = emails,
                    Header                 = messageHeader,
                    Message                = notificationAction.Message,
                    RevisionId             = message.RevisionId,
                    UserId                 = message.UserId,
                    ArtifactTypeId         = currentStateInfo.ItemTypeId,
                    ArtifactId             = artifactId,
                    ArtifactUrl            = artifactPartUrl,
                    ArtifactTypePredefined = artifact.Predefined,
                    ProjectId              = artifact.ProjectId,
                    BlueprintUrl           = blueprintUrl
                };

                if (notificationMessages.ContainsKey(artifactId))
                {
                    notificationMessages[artifactId].Add(notificationMessage);
                }
                else
                {
                    notificationMessages.Add(artifactId,
                                             new List <IWorkflowMessage>
                    {
                        notificationMessage
                    });
                }
            }
        }
        private static async Task ProcessSystemPropertyChange(TenantInformation tenant,
                                                              ArtifactsPublishedMessage message,
                                                              IArtifactsPublishedRepository repository,
                                                              List <EmailNotificationAction> notifications,
                                                              HashSet <PropertyTypePredefined> modifiedSystemPropertiesSet,
                                                              SqlWorkFlowStateInformation currentStateInfo,
                                                              List <PublishedArtifactInformation> updatedArtifacts,
                                                              int artifactId,
                                                              Dictionary <int, SqlWorkFlowStateInformation> workflowStates,
                                                              List <SqlProject> projects,
                                                              Dictionary <int, List <IWorkflowMessage> > notificationMessages)
        {
            if (modifiedSystemPropertiesSet.Count == 0)
            {
                return;
            }

            foreach (var notificationAction in notifications)
            {
                Logger.Log("Processing notification action", message, tenant, LogLevel.Debug);

                if (!notificationAction.EventPropertyTypeId.HasValue)
                {
                    continue;
                }

                int eventPropertyTypeId = notificationAction.EventPropertyTypeId.Value;

                // If system property provided is neither name or description
                if (eventPropertyTypeId != WorkflowConstants.PropertyTypeFakeIdName &&
                    eventPropertyTypeId != WorkflowConstants.PropertyTypeFakeIdDescription)
                {
                    Logger.Log(
                        $"The system property type ID {notificationAction.EventPropertyTypeId} is not supported. Only Name and Description are supported.",
                        message, tenant, LogLevel.Debug);
                    continue;
                }

                // If modified properties does not conatin event property type Id
                if (!modifiedSystemPropertiesSet.Contains(GetPropertyTypePredefined(notificationAction.EventPropertyTypeId.Value)))
                {
                    continue;
                }

                if (notificationAction.ConditionalStateId.HasValue &&
                    (currentStateInfo == null ||
                     currentStateInfo.WorkflowStateId != notificationAction.ConditionalStateId.Value))
                {
                    // The conditional state id is present, but either the current state info is not present or the current state is not same as conditional state
                    var currentStateId = currentStateInfo?.WorkflowStateId.ToString() ?? "none";
                    Logger.Log(
                        $"Conditional state ID {notificationAction.ConditionalStateId.Value} does not match current state ID: {currentStateId}",
                        message, tenant, LogLevel.Debug);
                    continue;
                }

                var artifact = updatedArtifacts.First(a => a.Id == artifactId);

                string messageHeader =
                    I18NHelper.FormatInvariant("You are being notified because artifact with Id: {0} has been updated.",
                                               artifactId);
                var artifactPartUrl = artifact.Url ?? ServerUriHelper.GetArtifactUrl(artifactId, true);
                var blueprintUrl    = artifact.BaseUrl ?? ServerUriHelper.GetBaseHostUri()?.ToString();
                var emails          = await WorkflowEventsMessagesHelper.GetEmailValues(message.RevisionId, artifactId,
                                                                                        notificationAction, repository.UsersRepository);

                var notificationMessage = new NotificationMessage
                {
                    TransactionId          = message.TransactionId,
                    ArtifactName           = workflowStates[artifactId].Name,
                    ProjectName            = projects.First(p => p.ItemId == artifact.ProjectId).Name,
                    Subject                = notificationAction.Subject,
                    From                   = notificationAction.FromDisplayName,
                    To                     = emails,
                    Header                 = messageHeader,
                    Message                = notificationAction.Message,
                    RevisionId             = message.RevisionId,
                    UserId                 = message.UserId,
                    ArtifactTypeId         = currentStateInfo.ItemTypeId,
                    ArtifactId             = artifactId,
                    ArtifactUrl            = artifactPartUrl,
                    ArtifactTypePredefined = artifact.Predefined,
                    ProjectId              = artifact.ProjectId,
                    BlueprintUrl           = blueprintUrl
                };

                if (notificationMessages.ContainsKey(artifactId))
                {
                    notificationMessages[artifactId].Add(notificationMessage);
                }
                else
                {
                    notificationMessages.Add(artifactId,
                                             new List <IWorkflowMessage>
                    {
                        notificationMessage
                    });
                }
            }
        }
        private static async Task <IWorkflowMessage> GetNotificationMessage(int userId,
                                                                            int revisionId,
                                                                            long transactionId,
                                                                            IBaseArtifactVersionControlInfo artifactInfo,
                                                                            string projectName,
                                                                            EmailNotificationAction notificationAction,
                                                                            string artifactUrl,
                                                                            string blueprintUrl,
                                                                            IUsersRepository usersRepository,
                                                                            IDbTransaction transaction)
        {
            string messageHeader   = I18NHelper.FormatInvariant("You are being notified because of an update to the artifact with Id: {0}.", artifactInfo.Id);
            var    artifactPartUrl = artifactUrl ?? ServerUriHelper.GetArtifactUrl(artifactInfo.Id, true);

            if (artifactPartUrl == null)
            {
                return(null);
            }
            var baseUrl = blueprintUrl ?? ServerUriHelper.GetBaseHostUri()?.ToString();
            var emails  = new List <string>();

            if (notificationAction.PropertyTypeId.HasValue && notificationAction.PropertyTypeId.Value > 0)
            {
                var userInfos =
                    await usersRepository.GetUserInfoForWorkflowArtifactForAssociatedUserProperty
                        (artifactInfo.Id,
                        notificationAction.PropertyTypeId.Value,
                        revisionId,
                        transaction);

                // Make sure that email is provided
                emails.AddRange(from userInfo in userInfos where !string.IsNullOrWhiteSpace(userInfo?.Email) select userInfo.Email);
            }
            else
            {
                // Take email from list of provided emails
                emails.AddRange(notificationAction.Emails ?? new List <string>());
            }

            var notificationMessage = new NotificationMessage
            {
                TransactionId          = transactionId,
                ArtifactName           = artifactInfo.Name,
                ProjectName            = projectName,
                Subject                = I18NHelper.FormatInvariant("Artifact {0} has been updated.", artifactInfo.Id),
                From                   = notificationAction.FromDisplayName,
                To                     = emails,
                Message                = notificationAction.Message,
                RevisionId             = revisionId,
                UserId                 = userId,
                ArtifactTypeId         = artifactInfo.ItemTypeId,
                ArtifactId             = artifactInfo.Id,
                ArtifactUrl            = artifactPartUrl,
                ArtifactTypePredefined = (int)artifactInfo.PredefinedType,
                ProjectId              = artifactInfo.ProjectId,
                Header                 = messageHeader,
                BlueprintUrl           = baseUrl
            };

            return(notificationMessage);
        }