Beispiel #1
0
        public async Task <ICommandResult <Reply> > SendAsync(INotificationContext <Reply> context)
        {
            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.NewReplyTag.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Get the entity for the reply
            var entity = await _entityStore.GetByIdAsync(context.Model.EntityId);

            // We always need an entity
            if (entity == null)
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <Reply>();

            // Build user notification
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = entity.Title,
                Message          = S["A reply has been posted with a tag your following"],
                CreatedUserId    = context.Model.CreatedUserId,
                Url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
                {
                    ["area"]         = "Plato.Discuss",
                    ["controller"]   = "Home",
                    ["action"]       = "Reply",
                    ["opts.id"]      = entity.Id,
                    ["opts.alias"]   = entity.Alias,
                    ["opts.replyId"] = context.Model.Id
                })
            };

            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #2
0
        // Private Methods

        async Task <Issue> EntityCreated(Issue entity)
        {
            // If the created entity is hidden, no need to send notifications
            // Entities can be hidden automatically, for example if they are detected as SPAM
            if (entity.IsHidden())
            {
                return(entity);;
            }

            // Build url to the entity
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            var url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]       = "Plato.Issues",
                ["controller"] = "Home",
                ["action"]     = "Display",
                ["opts.id"]    = entity.Id,
                ["opts.alias"] = entity.Alias
            });

            // Build the message to post to Slack
            var sb = new StringBuilder();

            sb
            .Append(entity.Title)
            .Append(" - ")
            .Append(baseUri)
            .Append(url);

            // Finally post our message to Slack
            var response = await _slackService.PostAsync(sb.ToString());

            // Log any errors that may have occurred
            if (!response.Success)
            {
                if (_logger.IsEnabled(LogLevel.Error))
                {
                    _logger.LogError($"An error occurred whilst attempting to post to Slack. Response from POST request to Slack Webhook Url: {response.Error}");
                }
            }

            // Continue processing the broker pipeline
            return(entity);
        }
Beispiel #3
0
        public async Task <ICommandResult <Article> > SendAsync(INotificationContext <Article> context)
        {
            // Create result
            var result = new CommandResult <Article>();

            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.NewLabel.Name, StringComparison.Ordinal))
            {
                return(result.Failed($"Skipping notification '{WebNotifications.NewLabel.Name}' as this does not match '{context.Notification.Type.Name}'."));
            }

            // Build user notification
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            // Build user notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = context.Model.Title,
                Message          = S["An article has been posted with a label your following"],
                CreatedUserId    = context.Model.CreatedUserId,
                Url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
                {
                    ["area"]       = "Plato.Articles",
                    ["controller"] = "Home",
                    ["action"]     = "Display",
                    ["opts.id"]    = context.Model.Id,
                    ["opts.alias"] = context.Model.Alias
                })
            };

            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #4
0
        public async Task <ICommandResult <Doc> > SendAsync(INotificationContext <Doc> context)
        {
            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.EntityUpdate.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <Doc>();

            // Get base Uri
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            // Build user notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = context.Model.Title,
                Message          = S["I've just updated a doc your following"],
                CreatedUserId    = context.Model.ModifiedUserId,
                Url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
                {
                    ["area"]       = "Plato.Docs",
                    ["controller"] = "Home",
                    ["action"]     = "Display",
                    ["opts.id"]    = context.Model.Id,
                    ["opts.alias"] = context.Model.Alias
                })
            };

            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #5
0
        public async Task <ICommandResult <ReportSubmission <Question> > > SendAsync(INotificationContext <ReportSubmission <Question> > context)
        {
            // Validate
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Notification == null)
            {
                throw new ArgumentNullException(nameof(context.Notification));
            }

            if (context.Notification.Type == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.Type));
            }

            if (context.Notification.To == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.To));
            }

            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.QuestionReport.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <ReportSubmission <Question> >();

            var baseUri = await _urlHelper.GetBaseUrlAsync();

            var url = _urlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]       = "Plato.Questions",
                ["controller"] = "Home",
                ["action"]     = "Display",
                ["opts.id"]    = context.Model.What.Id,
                ["opts.alias"] = context.Model.What.Alias
            });

            // Get reason given text
            var reasonText = S["Question Reported"];

            if (ReportReasons.Reasons.ContainsKey(context.Model.Why))
            {
                reasonText = S[ReportReasons.Reasons[context.Model.Why]];
            }

            //// Build notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = reasonText.Value,
                Message          = S["A question has been reported!"],
                Url           = url,
                CreatedUserId = context.Notification.From?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            };

            // Create notification
            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #6
0
        public async Task <ICommandResult <DocComment> > SendAsync(INotificationContext <DocComment> context)
        {
            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(EmailNotifications.NewDocComment.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <DocComment>();

            // Get the entity for the reply
            var entity = await _entityStore.GetByIdAsync(context.Model.EntityId);

            if (entity == null)
            {
                return(result.Failed($"No entity could be found with the Id of {context.Model.EntityId} when sending the follow notification '{EmailNotifications.NewDocComment.Name}'."));
            }

            // Get email template
            const string templateId = "NewDocComment";

            // Tasks run in a background thread and don't have access to HttpContext
            // Create a dummy principal to represent the user so we can still obtain
            // the current culture for the email
            var principal = await _claimsPrincipalFactory.CreateAsync((User)context.Notification.To);

            var culture = await _contextFacade.GetCurrentCultureAsync(principal.Identity);

            var email = await _localeStore.GetFirstOrDefaultByKeyAsync <LocaleEmail>(culture, templateId);

            if (email != null)
            {
                // Build entity url
                var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

                var url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
                {
                    ["area"]         = "Plato.Docs",
                    ["controller"]   = "Home",
                    ["action"]       = "Reply",
                    ["opts.id"]      = entity.Id,
                    ["opts.alias"]   = entity.Alias,
                    ["opts.replyId"] = context.Model.Id
                });

                // Build message from template
                var message = email.BuildMailMessage();
                message.Body = string.Format(
                    email.Message,
                    context.Notification.To.DisplayName,
                    entity.Title,
                    baseUri + url);
                message.IsBodyHtml = true;
                message.To.Add(new MailAddress(context.Notification.To.Email));

                // Send message
                var emailResult = await _emailManager.SaveAsync(message);

                if (emailResult.Succeeded)
                {
                    return(result.Success(context.Model));
                }

                return(result.Failed(emailResult.Errors?.ToArray()));
            }

            return(result.Failed($"No email template with the Id '{templateId}' exists within the 'locales/{culture}/emails.json' file!"));
        }
Beispiel #7
0
        public async Task <ICommandResult <Topic> > SendAsync(INotificationContext <Topic> context)
        {
            // Validate
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Notification == null)
            {
                throw new ArgumentNullException(nameof(context.Notification));
            }

            if (context.Notification.Type == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.Type));
            }

            if (context.Notification.To == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.To));
            }

            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.TopicSpam.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <Topic>();

            var baseUri = await _urlHelper.GetBaseUrlAsync();

            var url = _urlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]       = "Plato.Discuss",
                ["controller"] = "Home",
                ["action"]     = "Display",
                ["opts.id"]    = context.Model.Id,
                ["opts.alias"] = context.Model.Alias
            });

            //// Build notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = S["Possible SPAM"].Value,
                Message          = S["A topic has been detected as SPAM!"],
                Url           = url,
                CreatedUserId = context.Notification.From?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            };

            // Create notification
            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #8
0
        public async Task <ICommandResult <ReportSubmission <Issue> > > SendAsync(INotificationContext <ReportSubmission <Issue> > context)
        {
            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(EmailNotifications.IssueReport.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <ReportSubmission <Issue> >();

            // Get email template
            const string templateId = "NewIssueReport";

            // Tasks run in a background thread and don't have access to HttpContext
            // Create a dummy principal to represent the user so we can still obtain
            // the current culture for the email
            var principal = await _claimsPrincipalFactory.CreateAsync((User)context.Notification.To);

            var culture = await _contextFacade.GetCurrentCultureAsync(principal.Identity);

            var email = await _localeStore.GetFirstOrDefaultByKeyAsync <LocaleEmail>(culture, templateId);

            if (email == null)
            {
                return(result.Failed(
                           $"No email template with the Id '{templateId}' exists within the 'locales/{culture}/emails.json' file!"));
            }

            // Get reason given text
            var reasonText = S["No reason supplied"];

            if (ReportReasons.Reasons.ContainsKey(context.Model.Why))
            {
                reasonText = S[ReportReasons.Reasons[context.Model.Why]];
            }

            // Build entity url
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            var url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]       = "Plato.Issues",
                ["controller"] = "Home",
                ["action"]     = "Display",
                ["opts.id"]    = context.Model.What.Id,
                ["opts.alias"] = context.Model.What.Alias
            });

            // Build message from template
            var message = email.BuildMailMessage();

            message.Body = string.Format(
                email.Message,
                context.Notification.To.DisplayName,
                context.Model.What.Title,
                reasonText.Value,
                context.Model.Who.DisplayName,
                context.Model.Who.UserName,
                baseUri + url);

            message.IsBodyHtml = true;
            message.To.Add(new MailAddress(context.Notification.To.Email));

            // Send message
            var emailResult = await _emailManager.SaveAsync(message);

            if (emailResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(emailResult.Errors?.ToArray()));
        }
Beispiel #9
0
        public async Task <ICommandResult <Answer> > SendAsync(INotificationContext <Answer> context)
        {
            // Validate
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Notification == null)
            {
                throw new ArgumentNullException(nameof(context.Notification));
            }

            if (context.Notification.Type == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.Type));
            }

            if (context.Notification.To == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.To));
            }

            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.AnswerSpam.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <Answer>();

            // Get entity for reply
            var entity = await _entityStore.GetByIdAsync(context.Model.EntityId);

            // Ensure we found the entity
            if (entity == null)
            {
                return(result.Failed(
                           $"No entity with id '{context.Model.EntityId}' exists. Failed to send reply spam web notification."));
            }

            var baseUri = await _urlHelper.GetBaseUrlAsync();

            var url = _urlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]         = "Plato.Questions",
                ["controller"]   = "Home",
                ["action"]       = "Reply",
                ["opts.id"]      = entity.Id,
                ["opts.alias"]   = entity.Alias,
                ["opts.replyId"] = context.Model.Id
            });

            //// Build notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = S["Possible SPAM"].Value,
                Message          = S["A question answer has been detected as SPAM!"],
                Url           = url,
                CreatedUserId = context.Notification.From?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            };

            // Create notification
            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #10
0
        public async Task <ICommandResult <Badge> > SendAsync(INotificationContext <Badge> context)
        {
            // Validate
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Notification == null)
            {
                throw new ArgumentNullException(nameof(context.Notification));
            }

            if (context.Notification.Type == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.Type));
            }

            if (context.Notification.To == null)
            {
                throw new ArgumentNullException(nameof(context.Notification.To));
            }

            // Ensure correct notification provider
            if (!context.Notification.Type.Name.Equals(WebNotifications.NewBadge.Name, StringComparison.Ordinal))
            {
                return(null);
            }

            // Create result
            var result = new CommandResult <Badge>();

            var baseUri = await _urlHelper.GetBaseUrlAsync();

            var url = _urlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]       = "Plato.Users.Badges",
                ["controller"] = "Profile",
                ["action"]     = "Index",
                ["opts.id"]    = context.Notification.To.Id,
                ["opts.alias"] = context.Notification.To.Alias
            });

            //// Build notification
            var userNotification = new UserNotification()
            {
                NotificationName = context.Notification.Type.Name,
                UserId           = context.Notification.To.Id,
                Title            = context.Model.Title,
                Message          = $"{S["You've earned the"].Value} '{context.Model.Title}' {S["badge"].Value}",
                Url           = url,
                CreatedUserId = context.Notification.From?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            };

            // Create notification
            var userNotificationResult = await _userNotificationManager.CreateAsync(userNotification);

            if (userNotificationResult.Succeeded)
            {
                return(result.Success(context.Model));
            }

            return(result.Failed(userNotificationResult.Errors?.ToArray()));
        }
Beispiel #11
0
        // Private methods

        async Task <Answer> EntityReplyCreated(Answer reply)
        {
            // If the created reply is hidden, no need to send notifications
            // Replies can be hidden automatically, for example if they are detected as SPAM
            if (reply.IsHidden())
            {
                return(reply);;
            }

            // We need an entity to build the url
            if (reply.EntityId <= 0)
            {
                return(reply);
            }

            // Get entity
            var entity = await _entityStore.GetByIdAsync(reply.EntityId);

            // Ensure the entity exists
            if (entity == null)
            {
                return(reply);
            }

            // Build url to entity reply
            var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

            var url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
            {
                ["area"]         = "Plato.Questions",
                ["controller"]   = "Home",
                ["action"]       = "Reply",
                ["opts.id"]      = entity.Id,
                ["opts.alias"]   = entity.Alias,
                ["opts.replyId"] = reply.Id
            });

            // Build the message to post to Slack
            var sb = new StringBuilder();

            sb
            .Append("RE: ")
            .Append(entity.Title)
            .Append(" - ")
            .Append(baseUri)
            .Append(url);

            // Finally post our message to Slack
            var response = await _slackService.PostAsync(sb.ToString());

            // Log any errors that may have occurred
            if (!response.Success)
            {
                if (_logger.IsEnabled(LogLevel.Error))
                {
                    _logger.LogError($"An error occurred whilst attempting to post a reply to Slack. Response from POST request to Slack Webhook Url: {response.Error}");
                }
            }

            // Continue processing the broker pipeline
            return(reply);
        }
Beispiel #12
0
        public async Task <ICommandResult <FileInvite> > SendLinkInviteAsync(FileInvite invite)
        {
            if (invite == null)
            {
                throw new ArgumentException(nameof(invite));
            }

            // Create result
            var result = new CommandResult <FileInvite>();

            if (invite.FileId <= 0)
            {
                return(result.Failed(T["A file is required to share"].Value));
            }

            if (string.IsNullOrEmpty(invite.Email))
            {
                return(result.Failed(T["An email address is required"].Value));
            }

            // Get file
            var file = await _fileStore.GetByIdAsync(invite.FileId);

            // Ensure we found the file
            if (file == null)
            {
                return(result.Failed(T["The file could not be found"].Value));
            }

            // Get email template
            const string templateId = "ShareFileLink";

            // Configured culture
            var culture = await _contextFacade.GetCurrentCultureAsync();

            var email = await _localeStore.GetFirstOrDefaultByKeyAsync <LocaleEmail>(culture, templateId);

            if (email != null)
            {
                // Ensure email is safe for URL
                var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(invite.Email));

                // Build invite URL
                var baseUri = await _capturedRouterUrlHelper.GetBaseUrlAsync();

                var url = _capturedRouterUrlHelper.GetRouteUrl(baseUri, new RouteValueDictionary()
                {
                    ["area"]       = "Plato.Files.Sharing",
                    ["controller"] = "Home",
                    ["action"]     = "Index",
                    ["id"]         = invite.Id,
                    ["token"]      = token,
                    ["alias"]      = file.Alias
                });

                // Build message from template
                var message = email.BuildMailMessage();
                message.Subject = string.Format(
                    email.Subject,
                    invite.CreatedBy.DisplayName);
                message.Body = string.Format(
                    email.Message,
                    invite.CreatedBy.DisplayName,
                    file.Name,
                    file.ContentLength.ToFriendlyFileSize(),
                    baseUri + url);
                message.IsBodyHtml = true;
                message.To.Add(new MailAddress(invite.Email));

                // Send message
                var emailResult = await _emailManager.SaveAsync(message);

                if (emailResult.Succeeded)
                {
                    return(result.Success(invite));
                }

                return(result.Failed(emailResult.Errors?.ToArray()));
            }

            return(result.Failed($"No email template with the Id '{templateId}' exists within the 'locales/{culture}/emails.json' file!"));
        }