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); }
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); }