/// <inheritdoc /> public async Task <IPipelineProcess <Category> > Process(IPipelineProcess <Category> input, IMvcForumContext context) { _roleService.RefreshContext(context); _localizationService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; // See if we can get the username if (!string.IsNullOrWhiteSpace(username)) { // Get logged on user var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); if (loggedOnUser != null) { // Users role var loggedOnUsersRole = loggedOnUser.GetRole(_roleService); // Get the permissions and add to extendeddata as we'll use it again var permissions = _roleService.GetPermissions(input.EntityToProcess, loggedOnUsersRole); input.ExtendedData.Add(Constants.ExtendedDataKeys.PermissionSet, permissions); // Check user is admin if (!loggedOnUser.IsAdmin()) { input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); } } else { input.AddError("Unable to get user from username"); return(input); } } else { input.AddError("Unable to get username"); return(input); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Group> > Process(IPipelineProcess <Group> input, IMvcForumContext context) { _groupPermissionForRoleService.RefreshContext(context); _notificationService.RefreshContext(context); try { // Check if anyone else if using this role var okToDelete = !input.EntityToProcess.Topics.Any(); if (okToDelete) { // Get any Grouppermissionforoles and delete these first var rolesToDelete = _groupPermissionForRoleService.GetByGroup(input.EntityToProcess.Id); foreach (var GroupPermissionForRole in rolesToDelete) { _groupPermissionForRoleService.Delete(GroupPermissionForRole); } var GroupNotificationsToDelete = new List <GroupNotification>(); GroupNotificationsToDelete.AddRange(input.EntityToProcess.GroupNotifications); foreach (var GroupNotification in GroupNotificationsToDelete) { _notificationService.Delete(GroupNotification); } context.Group.Remove(input.EntityToProcess); await context.SaveChangesAsync(); _cacheService.ClearStartsWith("GroupList"); } else { input.AddError($"In use by {input.EntityToProcess.Topics} entities"); return(input); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Category> > Process(IPipelineProcess <Category> input, IMvcForumContext context) { _localizationService.RefreshContext(context); try { if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PostedFiles)) { // Sort image out first if (input.ExtendedData[Constants.ExtendedDataKeys.PostedFiles] is HttpPostedFileBase[] files) { // Before we save anything, check the user already has an upload folder and if not create one var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(ForumConfiguration.Instance.UploadFolderPath, input.EntityToProcess.Id)); if (!Directory.Exists(uploadFolderPath)) { Directory.CreateDirectory(uploadFolderPath ?? throw new InvalidOperationException()); } // Loop through each file and get the file info and save to the users folder and Db var file = files[0]; if (file != null) { // If successful then upload the file var uploadResult = file.UploadFile(uploadFolderPath, _localizationService, true); if (!uploadResult.UploadSuccessful) { input.AddError(uploadResult.ErrorMessage); return(input); } // Save avatar to user input.EntityToProcess.Image = uploadResult.UploadedFileName; await context.SaveChangesAsync(); } } } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _roleService.RefreshContext(context); _localizationService.RefreshContext(context); // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; // See if we can get the username if (!string.IsNullOrWhiteSpace(username)) { var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); var loggedOnUsersRole = loggedOnUser.GetRole(_roleService); var loggedOnUserId = loggedOnUser?.Id ?? Guid.Empty; var permissions = _roleService.GetPermissions(null, loggedOnUsersRole); if (loggedOnUsersRole.RoleName == Constants.AdminRoleName || loggedOnUserId == input.EntityToProcess.Id || permissions[ForumConfiguration.Instance.PermissionEditMembers].IsTicked) { input.Successful = true; input.ProcessLog.Add("Completed EditUserPermissionsPipe successfully"); return(input); } } // No permission input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _membershipService.RefreshContext(context); _localizationService.RefreshContext(context); try { // Scrub all member data var scrubResult = await _membershipService.ScrubUsers(input.EntityToProcess); if (!scrubResult.Successful) { input.AddError(scrubResult.ProcessLog.FirstOrDefault()); return(input); } // Just clear the roles, don't delete them input.EntityToProcess.Roles.Clear(); // Now delete the member context.MembershipUser.Remove(input.EntityToProcess); var saved = await context.SaveChangesAsync(); if (saved <= 0) { // Nothing saved input.AddError(_localizationService.GetResourceString("Errors.GenericMessage")); } else { input.ProcessLog.Add("Member deleted successfully"); } } catch (Exception ex) { _loggingService.Error(ex); input.AddError(ex.Message); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); _localizationService.RefreshContext(context); _spamService.RefreshContext(context); try { // Get the all the words I need var allWords = await context.BannedWord.ToListAsync(); // Do the stop words first foreach (var stopWord in allWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray()) { if (input.EntityToProcess.PostContent.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } // Check Akismet if (_spamService.IsSpam(input.EntityToProcess)) { input.EntityToProcess.Pending = true; input.ExtendedData.Add(Constants.ExtendedDataKeys.Moderate, true); } // Sanitise the banned words var bannedWords = allWords.Where(x => x.IsStopWord != true).Select(x => x.Word).ToArray(); input.EntityToProcess.PostContent = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.PostContent, bannedWords); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Group> > Process(IPipelineProcess <Group> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); _localizationService.RefreshContext(context); _spamService.RefreshContext(context); try { // Get the all the words I need var allWords = await context.BannedWord.ToListAsync(); // Do the stop words first foreach (var stopWord in allWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray()) { if (input.EntityToProcess.Name.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0 || input.EntityToProcess.Description.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } // Sanitise the banned words var bannedWords = allWords.Where(x => x.IsStopWord != true).Select(x => x.Word).ToArray(); input.EntityToProcess.Name = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Name, bannedWords); input.EntityToProcess.Description = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Description, bannedWords); } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUserPoints> > Process(IPipelineProcess <MembershipUserPoints> input, IMvcForumContext context) { try { if (input.EntityToProcess.Points != 0) { // Add Date input.EntityToProcess.DateAdded = DateTime.UtcNow; // Check this point has not already been awarded var canAddPoints = true; // Check to see if this has an id if (input.EntityToProcess.PointsForId != null) { var alreadyHasThisPoint = _membershipUserPointsService.GetByUser(input.EntityToProcess.User) .Any(x => x.PointsFor == input.EntityToProcess.PointsFor && x.PointsForId == input.EntityToProcess.PointsForId); canAddPoints = (alreadyHasThisPoint == false); } // If they can ad points let them if (canAddPoints) { context.MembershipUserPoints.Add(input.EntityToProcess); await context.SaveChangesAsync(); } } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { // Refresh contexts for all services _postEditService.RefreshContext(context); _membershipUserPointsService.RefreshContext(context); _settingsService.RefreshContext(context); _activityService.RefreshContext(context); _notificationService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); // Is this an edit? If so, create a post edit var isEdit = false; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.IsEdit)) { isEdit = input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] as bool? == true; } if (isEdit) { // Get the original post var originalPost = await context.Post.Include(x => x.Topic).FirstOrDefaultAsync(x => x.Id == input.EntityToProcess.Id); // Get content from Extended data var postedContent = input.ExtendedData[Constants.ExtendedDataKeys.Content] as string; input.EntityToProcess.PostContent = postedContent; // This is an edit of a post input.EntityToProcess.DateEdited = DateTime.Now; // Grab the original name out the extended data var topicName = input.ExtendedData[Constants.ExtendedDataKeys.Name] as string; if (!originalPost.PostContent.Equals(postedContent, StringComparison.OrdinalIgnoreCase) || !originalPost.Topic.Name.Equals(topicName, StringComparison.OrdinalIgnoreCase)) { // Create a post edit var postEdit = new PostEdit { Post = input.EntityToProcess, DateEdited = input.EntityToProcess.DateEdited, EditedBy = loggedOnUser, OriginalPostContent = originalPost.PostContent, OriginalPostTitle = originalPost.IsTopicStarter ? originalPost.Topic.Name : string.Empty }; // Add the post edit too _postEditService.Add(postEdit); } } else { // Add the post context.Post.Add(input.EntityToProcess); } // Now do a save await context.SaveChangesAsync(); // Update the users points score and post count for posting a new post if (!isEdit) { // make it last post if this is a new post input.EntityToProcess.Topic.LastPost = input.EntityToProcess; await _membershipUserPointsService.Add(new MembershipUserPoints { Points = _settingsService.GetSettings().PointsAddedPerPost, User = input.EntityToProcess.User, PointsFor = PointsFor.Post, PointsForId = input.EntityToProcess.Id }); // Add post activity if it's not an edit, or topic starter and it's not pending if (input.EntityToProcess.IsTopicStarter == false && input.EntityToProcess.Pending != true) { _activityService.PostCreated(input.EntityToProcess); } } if (input.EntityToProcess.IsTopicStarter == false && input.EntityToProcess.Pending != true) { // Send notifications _notificationService.Notify(input.EntityToProcess.Topic, loggedOnUser, NotificationType.Post); } // Now do a final save await context.SaveChangesAsync(); input.ProcessLog.Add("Post created successfully"); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Group> > Process(IPipelineProcess <Group> input, IMvcForumContext context) { _localizationService.RefreshContext(context); _groupService.RefreshContext(context); try { Guid?parentGroupGuid = null; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.ParentGroup)) { parentGroupGuid = input.ExtendedData[Constants.ExtendedDataKeys.ParentGroup] as Guid?; } // Sort if this is a section Section section = null; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.Section)) { if (input.ExtendedData[Constants.ExtendedDataKeys.Section] is Guid guid) { section = _groupService.GetSection(guid); } } // Sort the section - If it's null remove it input.EntityToProcess.Section = section ?? null; var isEdit = false; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.IsEdit)) { isEdit = input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] as bool? == true; } if (isEdit) { var parentCat = parentGroupGuid != null ? _groupService.Get(parentGroupGuid.Value) : null; // Check they are not trying to add a subGroup of this Group as the parent or it will break if (parentCat?.Path != null && parentGroupGuid != null) { var parentCats = parentCat.Path.Split(',').Where(x => !string.IsNullOrWhiteSpace(x)) .Select(x => new Guid(x)).ToList(); if (parentCats.Contains(input.EntityToProcess.Id)) { // Remove the parent Group, but still let them create the catgory parentGroupGuid = null; } } if (parentGroupGuid != null) { // Set the parent Group var parentGroup = _groupService.Get(parentGroupGuid.Value); input.EntityToProcess.Parent_GroupId = parentGroup; // Append the path from the parent Group _groupService.SortPath(input.EntityToProcess, parentGroup); } else { // Must access property (trigger lazy-loading) before we can set it to null (Entity Framework bug!!!) var triggerEfLoad = input.EntityToProcess.Parent_GroupId; input.EntityToProcess.Parent_GroupId = null; // Also clear the path input.EntityToProcess.Path = null; } Guid user = new Guid(); _groupService.UpdateSlugFromName(input.EntityToProcess, user); try { await context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { return(null); } } else { if (parentGroupGuid != null) { var parentGroup = await context.Group.FirstOrDefaultAsync(x => x.Id == parentGroupGuid.Value); input.EntityToProcess.Parent_GroupId = parentGroup; _groupService.SortPath(input.EntityToProcess, parentGroup); } // url slug generator input.EntityToProcess.Slug = ServiceHelpers.GenerateSlug(input.EntityToProcess.Name, _groupService.GetBySlugLike(ServiceHelpers.CreateUrl(input.EntityToProcess.Name)).Select(x => x.Slug).ToList(), null); // Add the Group context.Group.Add(input.EntityToProcess); } try { await context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { return(null); } _cacheService.ClearStartsWith("GroupList"); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { // Refresh the context in each of these services _voteService.RefreshContext(context); _membershipUserPointsService.RefreshContext(context); _uploadedFileService.RefreshContext(context); _favouriteService.RefreshContext(context); _postEditService.RefreshContext(context); _roleService.RefreshContext(context); _localizationService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); var loggedOnUsersRole = loggedOnUser.GetRole(_roleService); var permissions = _roleService.GetPermissions(input.EntityToProcess.Topic.Category, loggedOnUsersRole); if (input.EntityToProcess.User.Id == loggedOnUser.Id || permissions[ForumConfiguration.Instance.PermissionDeletePosts].IsTicked) { // Get the topic var topic = input.EntityToProcess.Topic; var votes = _voteService.GetVotesByPost(input.EntityToProcess.Id); #region Deleting Points // Remove the points the user got for this post await _membershipUserPointsService.Delete(input.EntityToProcess.User, PointsFor.Post, input.EntityToProcess.Id); // Also get all the votes and delete anything to do with those foreach (var postVote in votes) { await _membershipUserPointsService.Delete(PointsFor.Vote, postVote.Id); } // Also the mark as solution await _membershipUserPointsService.Delete(PointsFor.Solution, input.EntityToProcess.Id); #endregion await context.SaveChangesAsync(); #region Deleting Votes var votesToDelete = new List <Vote>(); votesToDelete.AddRange(votes); foreach (var vote in votesToDelete) { input.EntityToProcess.Votes.Remove(vote); _voteService.Delete(vote); } input.EntityToProcess.Votes.Clear(); #endregion #region Files // Clear files attached to post var filesToDelete = new List <UploadedFile>(); filesToDelete.AddRange(input.EntityToProcess.Files); foreach (var uploadedFile in filesToDelete) { // store the file path as we'll need it to delete on the file system var filePath = uploadedFile.FilePath; input.EntityToProcess.Files.Remove(uploadedFile); _uploadedFileService.Delete(uploadedFile); // And finally delete from the file system if (!string.IsNullOrWhiteSpace(filePath)) { var mapped = HostingEnvironment.MapPath(filePath); if (mapped != null) { File.Delete(mapped); } } } input.EntityToProcess.Files.Clear(); #endregion #region Favourites var postFavourites = new List <Favourite>(); postFavourites.AddRange(input.EntityToProcess.Favourites); foreach (var postFavourite in postFavourites) { input.EntityToProcess.Favourites.Remove(postFavourite); _favouriteService.Delete(postFavourite); } input.EntityToProcess.Favourites.Clear(); #endregion #region Post Edits var postEdits = new List <PostEdit>(); postEdits.AddRange(input.EntityToProcess.PostEdits); foreach (var postEdit in postEdits) { input.EntityToProcess.PostEdits.Remove(postEdit); _postEditService.Delete(postEdit); } input.EntityToProcess.PostEdits.Clear(); #endregion await context.SaveChangesAsync(); // Before we delete the post, we need to check if this is the last post in the topic // and if so update the topic if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.IgnoreLastPost)) { var ignoreLastPost = input.ExtendedData[Constants.ExtendedDataKeys.IgnoreLastPost] as bool?; if (ignoreLastPost == false) { var lastPost = topic.Posts.OrderByDescending(x => x.DateCreated).FirstOrDefault(); if (lastPost != null && lastPost.Id == input.EntityToProcess.Id) { // Get the new last post and update the topic topic.LastPost = topic.Posts.Where(x => x.Id != input.EntityToProcess.Id).OrderByDescending(x => x.DateCreated).FirstOrDefault(); } if (topic.Solved && input.EntityToProcess.IsSolution) { topic.Solved = false; } // Save the topic await context.SaveChangesAsync(); } } // Remove from the topic topic.Posts.Remove(input.EntityToProcess); // now delete the post context.Post.Remove(input.EntityToProcess); // Save changes await context.SaveChangesAsync(); } else { input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); } } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _membershipService.RefreshContext(context); _settingsService.RefreshContext(context); _localizationService.RefreshContext(context); _emailService.RefreshContext(context); _activityService.RefreshContext(context); try { if (string.IsNullOrWhiteSpace(input.EntityToProcess.UserName)) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.InvalidUserName)); input.Successful = false; return(input); } // get by username if (_membershipService.GetUser(input.EntityToProcess.UserName, true) != null) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.DuplicateUserName)); input.Successful = false; return(input); } // Add get by email address if (_membershipService.GetUserByEmail(input.EntityToProcess.Email, true) != null) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.DuplicateEmail)); input.Successful = false; return(input); } if (string.IsNullOrWhiteSpace(input.EntityToProcess.Password)) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.InvalidPassword)); input.Successful = false; return(input); } // Get the settings var settings = _settingsService.GetSettings(false); var manuallyAuthoriseMembers = settings.ManuallyAuthoriseNewMembers; var memberEmailAuthorisationNeeded = settings.NewMemberEmailConfirmation == true; // If this is a social login, and memberEmailAuthorisationNeeded is true then we need to ignore it // and set memberEmailAuthorisationNeeded to false because the email addresses are validated by the social media providers if (manuallyAuthoriseMembers || memberEmailAuthorisationNeeded) { input.EntityToProcess.IsApproved = false; } else { input.EntityToProcess.IsApproved = true; } input.EntityToProcess = context.MembershipUser.Add(input.EntityToProcess); var saved = await context.SaveChangesAsync(); if (saved <= 0) { input.ProcessLog.Add("Unable to save changes to the database"); input.Successful = false; return(input); } var inviteMailAddress = new MailAddress(input.EntityToProcess.Email); foreach (var invite in await _groupInviteService.GetInvitesForGroupAsync(inviteMailAddress, CancellationToken.None)) { if (invite.GroupId.HasValue) { if (await _groupService.JoinGroupApproveAsync(invite.GroupId.Value, input.EntityToProcess.Id, CancellationToken.None)) { await _groupInviteService.DeleteInviteAsync(invite.Id, CancellationToken.None); } } } // Now add a memberjoined activity _activityService.MemberJoined(input.EntityToProcess); // Set manuallyAuthoriseMembers, memberEmailAuthorisationNeeded in extendeddata input.ExtendedData.Add(Constants.ExtendedDataKeys.ManuallyAuthoriseMembers, manuallyAuthoriseMembers); input.ExtendedData.Add(Constants.ExtendedDataKeys.MemberEmailAuthorisationNeeded, memberEmailAuthorisationNeeded); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } if (input.Successful) { input.ProcessLog.Add("CreateNewUserPipe Successful"); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _membershipService.RefreshContext(context); _localizationService.RefreshContext(context); _activityService.RefreshContext(context); try { // Grab out the image if we have one if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PostedFiles)) { // Check we're good if (input.ExtendedData[Constants.ExtendedDataKeys.PostedFiles] is HttpPostedFileBase avatar) { // Before we save anything, check the user already has an upload folder and if not create one var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(ForumConfiguration.Instance.UploadFolderPath, input.EntityToProcess.Id)); // If successful then upload the file var uploadResult = avatar.UploadFile(uploadFolderPath, _localizationService, true); // throw error if unsuccessful if (!uploadResult.UploadSuccessful) { input.AddError(uploadResult.ErrorMessage); return(input); } // Save avatar input.EntityToProcess.Avatar = uploadResult.UploadedFileName; } } // Edit the user now - Get the original from the database var dbUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.Id == input.EntityToProcess.Id); // User is trying to change username, need to check if a user already exists // with the username they are trying to change to var changedUsername = false; if (dbUser.UserName != input.EntityToProcess.UserName) { if (_membershipService.GetUser(input.EntityToProcess.UserName) != null) { input.AddError(_localizationService.GetResourceString("Members.Errors.DuplicateUserName")); return(input); } changedUsername = true; } // Add username changed to extended data input.ExtendedData.Add(Constants.ExtendedDataKeys.UsernameChanged, changedUsername); // User is trying to update their email address, need to // check the email is not already in use if (dbUser.Email != input.EntityToProcess.Email) { // Add get by email address if (_membershipService.GetUserByEmail(input.EntityToProcess.Email) != null) { input.AddError(_localizationService.GetResourceString("Members.Errors.DuplicateEmail")); return(input); } } // Add an activity _activityService.ProfileUpdated(input.EntityToProcess); // Save the user var saved = await context.SaveChangesAsync(); if (saved <= 0) { input.AddError(_localizationService.GetResourceString("Errors.GenericMessage")); } } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { _localizationService.RefreshContext(context); _topicService.RefreshContext(context); _postService.RefreshContext(context); try { // Do we have a topic title in the extended data var newTopicTitle = string.Empty; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.Name)) { newTopicTitle = input.ExtendedData[Constants.ExtendedDataKeys.Name] as string; } // Do we have a topic id in the extended data Guid?newTopicId = null; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.TopicId)) { newTopicId = input.ExtendedData[Constants.ExtendedDataKeys.TopicId] as Guid?; } // Flag whether we should also move any reply to posts var moveReplayPosts = input.ExtendedData[Constants.ExtendedDataKeys.MovePosts] as bool?; // Hold the previous topic var previousTopic = input.EntityToProcess.Topic; // Hold the previous category var category = input.EntityToProcess.Topic.Category; // Hold the post creator var postCreator = input.EntityToProcess.User; // Hold the topic Topic topic; // If the dropdown has a value, then we choose that first if (newTopicId != null) { // Get the selected topic topic = _topicService.Get(newTopicId.Value); } else if (!string.IsNullOrWhiteSpace(newTopicTitle)) { // If we get here, we use the topic create pipeline!! // Create the topic topic = new Topic { Name = newTopicTitle, Category = category, User = postCreator }; // Run the create pipeline var createPipeLine = await _topicService.Create(topic, null, string.Empty, true, input.EntityToProcess.PostContent, null); if (createPipeLine.Successful == false) { // Tell the user the topic is awaiting moderation input.AddError(createPipeLine.ProcessLog.FirstOrDefault()); return(input); } // Set the post to be a topic starter input.EntityToProcess.IsTopicStarter = true; // Save the changes await context.SaveChangesAsync(); // Set the topic topic = createPipeLine.EntityToProcess; } else { // No selected topic OR topic title, just redirect back to the topic return(input); } // Now update the post to the new topic input.EntityToProcess.Topic = topic; // Also move any posts, which were in reply to this post if (moveReplayPosts == true) { var relatedPosts = _postService.GetReplyToPosts(input.EntityToProcess.Id); foreach (var relatedPost in relatedPosts) { relatedPost.Topic = topic; } } var saveChanges = await context.SaveChangesAsync(); if (saveChanges <= 0) { // Nothing was saved so throw error message input.AddError(_localizationService.GetResourceString("Errors.GenericMessage")); return(input); } // Update Last post.. As we have done a save, we should get all posts including the added ones var lastPost = topic.Posts.OrderByDescending(x => x.DateCreated).FirstOrDefault(); topic.LastPost = lastPost; // If any of the posts we are moving, were the last post - We need to update the old Topic var previousTopicLastPost = previousTopic.Posts.OrderByDescending(x => x.DateCreated).FirstOrDefault(); previousTopic.LastPost = previousTopicLastPost; // Do a final save saveChanges = await context.SaveChangesAsync(); if (saveChanges <= 0) { // Nothing was saved so throw error message input.AddError(_localizationService.GetResourceString("Errors.GenericMessage")); return(input); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _postService.RefreshContext(context); _localizationService.RefreshContext(context); _pollService.RefreshContext(context); try { // Create the post HttpPostedFileBase[] files = null; if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PostedFiles)) { files = input.ExtendedData[Constants.ExtendedDataKeys.PostedFiles] as HttpPostedFileBase[]; } // Are we in an edit mode var isEdit = input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] as bool? == true; // Add a variable for the post Post post = null; // See if we have a post already (i.e. for when we move) if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.Post)) { // We have a post so set it post = input.ExtendedData[Constants.ExtendedDataKeys.Post] as Post; } // If the post is not null and we are not editing if (post != null && !isEdit) { // Set the topic post.Topic = input.EntityToProcess; } else { // Get the correct pipeline IPipelineProcess <Post> postPipelineResult; // Is this an edit if (isEdit) { // Get the topic starter post post = input.EntityToProcess.Posts.FirstOrDefault(x => x.IsTopicStarter); // Pass to edit postPipelineResult = await _postService.Edit(post, files, true, input.ExtendedData[Constants.ExtendedDataKeys.Name] as string, input.ExtendedData[Constants.ExtendedDataKeys.Content] as string); } else { if (input.EntityToProcess.Poll != null) { context.Poll.Add(input.EntityToProcess.Poll); } // Add the topic to the context context.Topic.Add(input.EntityToProcess); // We are creating a new post postPipelineResult = await _postService.Create( input.ExtendedData[Constants.ExtendedDataKeys.Content] as string, input.EntityToProcess, input.EntityToProcess.User, files, true, null); } // If there is an issue return the pipeline if (!postPipelineResult.Successful) { input.AddError(postPipelineResult.ProcessLog.FirstOrDefault()); return(input); } } // Do a final save await context.SaveChangesAsync(); // Sort the poll, if this is an edit we need to refresh and save the poll data if (isEdit) { var newPollAnswers = input.ExtendedData[Constants.ExtendedDataKeys.PollNewAnswers] as List <PollAnswer>; var pollCloseafterDays = input.ExtendedData[Constants.ExtendedDataKeys.PollCloseAfterDays] as int?; _pollService.RefreshEditedPoll(input.EntityToProcess, newPollAnswers, pollCloseafterDays ?? 0); } // Clear some caches _cacheService.ClearStartsWith("HotTopics"); } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); try { var email = input.EntityToProcess.Email; var userName = input.EntityToProcess.UserName; // Grab the email from the banned list var emailIsBanned = await context.BannedEmail.AnyAsync(x => x.Email == email); if (emailIsBanned == false) { // Email is ok, now check for banned words // Doesn't matter if it's a stop word or banned word, we'll reject it var allBannedWords = await context.BannedWord.ToListAsync(); var allStopWords = allBannedWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray(); // Loop banned Words foreach (var bannedWord in allBannedWords) { // Email if (email.ContainsCaseInsensitive(bannedWord.Word)) { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The email {email} contains a stop word"); return(input); } // Username if (userName.ContainsCaseInsensitive(bannedWord.Word)) { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The Username {userName} contains a stop word"); return(input); } } // Loop all stop words // Santise the fields now var justBannedWord = allBannedWords.Where(x => x.IsStopWord == false).Select(x => x.Word).ToArray(); } else { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The email {email} is banned"); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } if (input.Successful) { input.ProcessLog.Add("CheckBannedWordsPipe completed successfully"); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); _localizationService.RefreshContext(context); _spamService.RefreshContext(context); try { // Get the all the words I need var allWords = await context.BannedWord.ToListAsync(); var hasPollAnswers = input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PollNewAnswers); var newPollAnswers = new List <PollAnswer>(); if (hasPollAnswers) { newPollAnswers = input.ExtendedData[Constants.ExtendedDataKeys.PollNewAnswers] as List <PollAnswer>; } // Do the stop words first foreach (var stopWord in allWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray()) { // Check name if (input.EntityToProcess.Name.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } // Check poll answers on entity or ones we are waiting to update if (input.EntityToProcess.Poll != null && input.EntityToProcess.Poll.PollAnswers.Any()) { foreach (var pollAnswer in input.EntityToProcess.Poll.PollAnswers) { if (pollAnswer.Answer.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } if (hasPollAnswers) { if (newPollAnswers != null) { foreach (var pollAnswer in newPollAnswers) { if (pollAnswer.Answer.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } } // Check tags if (input.EntityToProcess.Tags != null && input.EntityToProcess.Tags.Any()) { foreach (var topicTag in input.EntityToProcess.Tags) { if (topicTag.Tag.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } } // Check Akismet if (_spamService.IsSpam(input.EntityToProcess)) { input.EntityToProcess.Pending = true; input.ExtendedData.Add(Constants.ExtendedDataKeys.Moderate, true); } // Sanitise the banned words var bannedWords = allWords.Where(x => x.IsStopWord != true).Select(x => x.Word).ToArray(); // Topic name input.EntityToProcess.Name = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Name, bannedWords); // Flood Check - Only if we are not editing // Are we in an edit mode var isEdit = input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] as bool? == true; if (!isEdit) { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); if (loggedOnUser != null) { if (!_topicService.PassedTopicFloodTest(input.EntityToProcess.Name, loggedOnUser)) { input.AddError(_localizationService.GetResourceString("Spam.FloodTestFailed")); return(input); } } else { input.AddError("Unable to get user from username"); return(input); } } // Sanitise Poll if (input.EntityToProcess.Poll != null && input.EntityToProcess.Poll.PollAnswers.Any()) { foreach (var pollAnswer in input.EntityToProcess.Poll.PollAnswers) { pollAnswer.Answer = _bannedWordService.SanitiseBannedWords(pollAnswer.Answer, bannedWords); } } // Santise new poll answers if (hasPollAnswers) { if (newPollAnswers != null) { foreach (var pollAnswer in newPollAnswers) { pollAnswer.Answer = _bannedWordService.SanitiseBannedWords(pollAnswer.Answer, bannedWords); } // Now re-assign them input.ExtendedData[Constants.ExtendedDataKeys.PollNewAnswers] = newPollAnswers; } } // Sanitise Tags if (input.EntityToProcess.Tags != null && input.EntityToProcess.Tags.Any()) { foreach (var topicTag in input.EntityToProcess.Tags) { topicTag.Tag = _bannedWordService.SanitiseBannedWords(topicTag.Tag, bannedWords); } } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _notificationService.RefreshContext(context); _activityService.RefreshContext(context); _localizationService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); // Are we in an edit mode var isEdit = input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] as bool? == true; // If the topic has tags then process if (input.EntityToProcess.Tags != null && input.EntityToProcess.Tags.Any()) { // Don't throw if badge fails as it's logged //await _badgeService.ProcessBadge(BadgeType.Tag, input.EntityToProcess.User); } if (isEdit == false) { // Subscribe the user to the topic as they have checked the checkbox if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.Subscribe)) { var subscribe = input.ExtendedData[Constants.ExtendedDataKeys.Subscribe] as bool?; if (subscribe == true) { var alreadyHasNotification = await context.TopicNotification .Include(x => x.Topic) .Include(x => x.User) .AnyAsync(x => x.Topic.Id == input.EntityToProcess.Id && x.User.Id == loggedOnUser.Id); if (alreadyHasNotification == false) { // Create the notification var topicNotification = new TopicNotification { Topic = input.EntityToProcess, User = loggedOnUser }; //save _notificationService.Add(topicNotification); } } } // Should we add the topic created activity if (input.EntityToProcess.Pending != true) { _activityService.TopicCreated(input.EntityToProcess); } // finally notify _notificationService.Notify(input.EntityToProcess, loggedOnUser, NotificationType.Topic); } // Was the post successful await context.SaveChangesAsync(); } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _localizationService.RefreshContext(context); _membershipService.RefreshContext(context); try { var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; var password = input.ExtendedData[Constants.ExtendedDataKeys.Password] as string; // Validate login if (_membershipService.ValidateUser(username, password, Membership.MaxInvalidPasswordAttempts)) { // Set last login date as users details are ok input.EntityToProcess = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); if (input.EntityToProcess.IsApproved && !input.EntityToProcess.IsLockedOut && !input.EntityToProcess.IsBanned) { input.EntityToProcess.LastLoginDate = DateTime.Now; input.Successful = true; return(input); } input.Successful = false; input.ProcessLog.Clear(); if (input.EntityToProcess.IsLockedOut) { input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.UserLockedOut")); } if (!input.EntityToProcess.IsApproved) { input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.UserNotApproved")); } if (input.EntityToProcess.IsBanned) { input.ProcessLog.Add(_localizationService.GetResourceString("Members.NowBanned")); } } else { // get here Login failed, check the login status var loginStatus = _membershipService.LastLoginStatus; input.Successful = false; input.ProcessLog.Clear(); switch (loginStatus) { case LoginAttemptStatus.UserNotFound: case LoginAttemptStatus.PasswordIncorrect: input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.PasswordIncorrect")); break; case LoginAttemptStatus.PasswordAttemptsExceeded: input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.PasswordAttemptsExceeded")); break; case LoginAttemptStatus.UserLockedOut: input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.UserLockedOut")); break; case LoginAttemptStatus.Banned: input.ProcessLog.Add(_localizationService.GetResourceString("Members.NowBanned")); break; case LoginAttemptStatus.UserNotApproved: input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.UserNotApproved")); break; default: input.ProcessLog.Add(_localizationService.GetResourceString("Members.Errors.LogonGeneric")); break; } } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _voteService.RefreshContext(context); _notificationService.RefreshContext(context); _favouriteService.RefreshContext(context); _membershipUserPointsService.RefreshContext(context); _activityService.RefreshContext(context); _pollService.RefreshContext(context); _topicService.RefreshContext(context); _groupService.RefreshContext(context); _postService.RefreshContext(context); try { // Delete all topics var topics = input.EntityToProcess.Topics; if (topics != null && topics.Any()) { var topicList = new List <Topic>(); topicList.AddRange(topics); foreach (var topic in topicList) { var topicDeleteResult = await _topicService.Delete(topic); if (!topicDeleteResult.Successful) { input.AddError(topicDeleteResult.ProcessLog.FirstOrDefault()); return(input); } } input.EntityToProcess.Topics.Clear(); await context.SaveChangesAsync(); } // Now sorts Last Posts on topics and delete all the users posts var posts = input.EntityToProcess.Posts; if (posts != null && posts.Any()) { var postIds = posts.Select(x => x.Id).ToList(); // Get all Groups var allGroups = _groupService.GetAll(input.EntityToProcess.Id); // Need to see if any of these are last posts on Topics // If so, need to swap out last post var lastPostTopics = _topicService.GetTopicsByLastPost(postIds, allGroups.ToList()); foreach (var topic in lastPostTopics.Where(x => x.User.Id != input.EntityToProcess.Id)) { var lastPost = topic.Posts.Where(x => !postIds.Contains(x.Id)) .OrderByDescending(x => x.DateCreated) .FirstOrDefault(); topic.LastPost = lastPost; } await context.SaveChangesAsync(); // Delete all posts var postList = new List <Post>(); postList.AddRange(posts); foreach (var post in postList) { // Delete post via pipeline var postDeleteResult = await _postService.Delete(post, true); if (!postDeleteResult.Successful) { input.AddError(postDeleteResult.ProcessLog.FirstOrDefault()); return(input); } } input.EntityToProcess.UploadedFiles.Clear(); input.EntityToProcess.Posts.Clear(); await context.SaveChangesAsync(); } // User Votes if (input.EntityToProcess.Votes != null) { var votesToDelete = new List <Vote>(); votesToDelete.AddRange(input.EntityToProcess.Votes); votesToDelete.AddRange(input.EntityToProcess.VotesGiven); foreach (var d in votesToDelete) { _voteService.Delete(d); } input.EntityToProcess.Votes.Clear(); input.EntityToProcess.VotesGiven.Clear(); await context.SaveChangesAsync(); } // User Group notifications if (input.EntityToProcess.GroupNotifications != null) { var toDelete = new List <GroupNotification>(); toDelete.AddRange(input.EntityToProcess.GroupNotifications); foreach (var obj in toDelete) { _notificationService.Delete(obj); } input.EntityToProcess.GroupNotifications.Clear(); await context.SaveChangesAsync(); } // User Favourites if (input.EntityToProcess.Favourites != null) { var toDelete = new List <Favourite>(); toDelete.AddRange(input.EntityToProcess.Favourites); foreach (var obj in toDelete) { _favouriteService.Delete(obj); } input.EntityToProcess.Favourites.Clear(); await context.SaveChangesAsync(); } if (input.EntityToProcess.TopicNotifications != null) { var notificationsToDelete = new List <TopicNotification>(); notificationsToDelete.AddRange(input.EntityToProcess.TopicNotifications); foreach (var topicNotification in notificationsToDelete) { _notificationService.Delete(topicNotification); } input.EntityToProcess.TopicNotifications.Clear(); } // Also clear their points var userPoints = input.EntityToProcess.Points; if (userPoints.Any()) { var pointsList = new List <MembershipUserPoints>(); pointsList.AddRange(userPoints); foreach (var point in pointsList) { point.User = null; await _membershipUserPointsService.Delete(point); } input.EntityToProcess.Points.Clear(); } // Now clear all activities for this user var usersActivities = _activityService.GetDataFieldByGuid(input.EntityToProcess.Id); _activityService.Delete(usersActivities.ToList()); await context.SaveChangesAsync(); // Also clear their poll votes var userPollVotes = input.EntityToProcess.PollVotes; if (userPollVotes.Any()) { var pollList = new List <PollVote>(); pollList.AddRange(userPollVotes); foreach (var vote in pollList) { vote.User = null; _pollService.Delete(vote); } input.EntityToProcess.PollVotes.Clear(); await context.SaveChangesAsync(); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _membershipService.RefreshContext(context); _settingsService.RefreshContext(context); _localizationService.RefreshContext(context); _emailService.RefreshContext(context); _activityService.RefreshContext(context); try { if (string.IsNullOrWhiteSpace(input.EntityToProcess.UserName)) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.InvalidUserName)); input.Successful = false; return(input); } // get by username if (_membershipService.GetUser(input.EntityToProcess.UserName, true) != null) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.DuplicateUserName)); input.Successful = false; return(input); } // Add get by email address if (_membershipService.GetUserByEmail(input.EntityToProcess.Email, true) != null) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.DuplicateEmail)); input.Successful = false; return(input); } if (string.IsNullOrWhiteSpace(input.EntityToProcess.Password)) { input.ProcessLog.Clear(); input.ProcessLog.Add(_membershipService.ErrorCodeToString(MembershipCreateStatus.InvalidPassword)); input.Successful = false; return(input); } // Get the settings var settings = _settingsService.GetSettings(false); var manuallyAuthoriseMembers = settings.ManuallyAuthoriseNewMembers; var memberEmailAuthorisationNeeded = settings.NewMemberEmailConfirmation == true; // Check social login var isSocialLogin = !string.IsNullOrWhiteSpace(input.EntityToProcess.FacebookAccessToken) || !string.IsNullOrWhiteSpace(input.EntityToProcess.GoogleAccessToken) || !string.IsNullOrWhiteSpace(input.EntityToProcess.MicrosoftAccessToken); // If this is a social login, and memberEmailAuthorisationNeeded is true then we need to ignore it // and set memberEmailAuthorisationNeeded to false because the email addresses are validated by the social media providers if (isSocialLogin && manuallyAuthoriseMembers == false) { memberEmailAuthorisationNeeded = false; input.EntityToProcess.IsApproved = true; } else if (manuallyAuthoriseMembers || memberEmailAuthorisationNeeded) { input.EntityToProcess.IsApproved = false; } else { input.EntityToProcess.IsApproved = true; } // See if this is a social login and we have their profile pic var socialProfileImageUrl = input.EntityToProcess.GetExtendedDataItem(Constants.ExtendedDataKeys.SocialProfileImageUrl); if (!string.IsNullOrWhiteSpace(socialProfileImageUrl)) { // We have an image url - Need to save it to their profile var image = socialProfileImageUrl.GetImageFromExternalUrl(); // Set upload directory - Create if it doesn't exist var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(ForumConfiguration.Instance.UploadFolderPath, input.EntityToProcess.Id)); if (uploadFolderPath != null && !Directory.Exists(uploadFolderPath)) { Directory.CreateDirectory(uploadFolderPath); } // Get the file name var fileName = Path.GetFileName(socialProfileImageUrl); // Create a HttpPostedFileBase image from the C# Image using (var stream = new MemoryStream()) { // Microsoft doesn't give you a file extension - See if it has a file extension // Get the file extension var fileExtension = Path.GetExtension(fileName); // Fix invalid Illegal charactors var regexSearch = $"{new string(Path.GetInvalidFileNameChars())}{new string(Path.GetInvalidPathChars())}"; var reg = new Regex($"[{Regex.Escape(regexSearch)}]"); fileName = reg.Replace(fileName, ""); if (string.IsNullOrWhiteSpace(fileExtension)) { // no file extension so give it one fileName = string.Concat(fileName, ".jpg"); } image.Save(stream, ImageFormat.Jpeg); stream.Position = 0; HttpPostedFileBase formattedImage = new MemoryFile(stream, "image/jpeg", fileName); // Upload the file var uploadResult = formattedImage.UploadFile(uploadFolderPath, _localizationService, true); // Don't throw error if problem saving avatar, just don't save it. if (uploadResult.UploadSuccessful) { input.EntityToProcess.Avatar = uploadResult.UploadedFileName; } } } input.EntityToProcess = context.MembershipUser.Add(input.EntityToProcess); var saved = await context.SaveChangesAsync(); if (saved <= 0) { input.ProcessLog.Add("Unable to save changes to the database"); input.Successful = false; return(input); } if (settings.EmailAdminOnNewMemberSignUp) { var sb = new StringBuilder(); sb.Append( $"<p>{string.Format(_localizationService.GetResourceString("Members.NewMemberRegistered"), settings.ForumName, settings.ForumUrl)}</p>"); sb.Append($"<p>{input.EntityToProcess.UserName} - {input.EntityToProcess.Email}</p>"); var email = new Email { EmailTo = settings.AdminEmailAddress, NameTo = _localizationService.GetResourceString("Members.Admin"), Subject = _localizationService.GetResourceString("Members.NewMemberSubject") }; email.Body = _emailService.EmailTemplate(email.NameTo, sb.ToString()); _emailService.SendMail(email); } // Only send the email if the admin is not manually authorising emails or it's pointless _emailService.SendEmailConfirmationEmail(input.EntityToProcess, manuallyAuthoriseMembers, memberEmailAuthorisationNeeded); // Now add a memberjoined activity _activityService.MemberJoined(input.EntityToProcess); // Set manuallyAuthoriseMembers, memberEmailAuthorisationNeeded in extendeddata input.ExtendedData.Add(Constants.ExtendedDataKeys.ManuallyAuthoriseMembers, manuallyAuthoriseMembers); input.ExtendedData.Add(Constants.ExtendedDataKeys.MemberEmailAuthorisationNeeded, memberEmailAuthorisationNeeded); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } if (input.Successful) { input.ProcessLog.Add("CreateNewUserPipe Successful"); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _roleService.RefreshContext(context); _topicService.RefreshContext(context); _localizationService.RefreshContext(context); _topicTagService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; // IS this an existing topic var existingTopic = await context.Topic.FirstOrDefaultAsync(x => x.Id == input.EntityToProcess.Id); if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.IsEdit)) { input.ExtendedData[Constants.ExtendedDataKeys.IsEdit] = existingTopic != null; } else { input.ExtendedData.Add(Constants.ExtendedDataKeys.IsEdit, existingTopic != null); } // See if we can get the username if (!string.IsNullOrWhiteSpace(username)) { // Get logged on user var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); if (loggedOnUser != null) { // Users role var loggedOnUsersRole = loggedOnUser.GetRole(_roleService); // Get the permissions and add to extendeddata as we'll use it again var permissions = _roleService.GetPermissions(input.EntityToProcess.Category, loggedOnUsersRole); input.ExtendedData.Add(Constants.ExtendedDataKeys.PermissionSet, permissions); // Flood Check if (!_topicService.PassedTopicFloodTest(input.EntityToProcess.Name, loggedOnUser)) { input.AddError(_localizationService.GetResourceString("Spam.FloodTestFailed")); return(input); } // Quick check to see if user is locked out, when logged in if (loggedOnUser.IsLockedOut || loggedOnUser.DisablePosting == true || !loggedOnUser.IsApproved) { FormsAuthentication.SignOut(); input.AddError(_localizationService.GetResourceString("Errors.NoAccess")); return(input); } // Finally check permissions if (permissions[ForumConfiguration.Instance.PermissionDenyAccess].IsTicked || permissions[ForumConfiguration.Instance.PermissionReadOnly].IsTicked || !permissions[ForumConfiguration.Instance.PermissionCreateTopics].IsTicked) { input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); } // Check for moderation on Category if (input.EntityToProcess.Category.ModerateTopics == true) { input.EntityToProcess.Pending = true; input.ExtendedData.Add(Constants.ExtendedDataKeys.Moderate, true); } // Check Is Locked if (existingTopic != null) { // If the locked has changed from original, check they have permission to change it if (existingTopic.IsLocked != input.EntityToProcess.IsLocked && permissions[ForumConfiguration.Instance.PermissionLockTopics].IsTicked == false) { // Put it back input.EntityToProcess.IsLocked = existingTopic.IsLocked; } } else if (input.EntityToProcess.IsLocked && permissions[ForumConfiguration.Instance.PermissionLockTopics].IsTicked == false) { // Put it back as not permission input.EntityToProcess.IsLocked = false; } // Check Sticky if (existingTopic != null) { // If the locked has changed from original, check they have permission to change it if (existingTopic.IsSticky != input.EntityToProcess.IsSticky && permissions[ForumConfiguration.Instance.PermissionCreateStickyTopics].IsTicked == false) { // Put it back input.EntityToProcess.IsSticky = existingTopic.IsSticky; } } else if (input.EntityToProcess.IsSticky && permissions[ForumConfiguration.Instance.PermissionCreateStickyTopics].IsTicked == false) { // Put it back as not permission input.EntityToProcess.IsSticky = false; } // Finally check for a poll if (input.EntityToProcess.Poll != null && input.EntityToProcess.Poll.PollAnswers.Any()) { if (permissions[ForumConfiguration.Instance.PermissionCreatePolls].IsTicked == false) { input.AddError(_localizationService.GetResourceString("Errors.NoPermissionPolls")); return(input); } } // Sort out tags so we can check permission for any new ones added if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.Tags)) { var tags = _topicTagService.CreateTagsFromCsv(input.ExtendedData[Constants.ExtendedDataKeys.Tags] as string); // Add the tags they are allowed to _topicTagService.Add(tags.ToArray(), input.EntityToProcess, permissions[ForumConfiguration.Instance.PermissionCreateTags].IsTicked); } } else { input.AddError("Unable to get user from username"); return(input); } } else { input.AddError("Unable to get username"); return(input); } } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { _localizationService.RefreshContext(context); _uploadedFileService.RefreshContext(context); try { // Files if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PostedFiles)) { // Get the files if (input.ExtendedData[Constants.ExtendedDataKeys.PostedFiles] is HttpPostedFileBase[] files) { if (files.Any(x => x != null)) { // Username var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; // Loggedonuser var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); // Before we save anything, check the user already has an upload folder and if not create one var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(ForumConfiguration.Instance.UploadFolderPath, loggedOnUser.Id)); if (!Directory.Exists(uploadFolderPath)) { Directory.CreateDirectory(uploadFolderPath); } // Loop through each file and get the file info and save to the users folder and Db foreach (var file in files) { if (file != null) { // If successful then upload the file var uploadResult = file.UploadFile(uploadFolderPath, _localizationService); if (!uploadResult.UploadSuccessful) { input.AddError(uploadResult.ErrorMessage); return(input); } // Add the filename to the database var uploadedFile = new UploadedFile { Filename = uploadResult.UploadedFileName, Post = input.EntityToProcess, MembershipUser = input.EntityToProcess.User }; _uploadedFileService.Add(uploadedFile); } } // Was the post successful if (await context.SaveChangesAsync() <= 0) { // Problem input.AddError(_localizationService.GetResourceString("Errors.GenericMessage")); } } } } } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Post> > Process(IPipelineProcess <Post> input, IMvcForumContext context) { _roleService.RefreshContext(context); _localizationService.RefreshContext(context); try { // Get the Current user from ExtendedData var username = input.ExtendedData[Constants.ExtendedDataKeys.Username] as string; // IS this an existing topic var existingPost = await context.Post.Include(x => x.User) .FirstOrDefaultAsync(x => x.Id == input.EntityToProcess.Id); input.ExtendedData.Add(Constants.ExtendedDataKeys.IsEdit, existingPost != null); // See if we can get the username if (!string.IsNullOrWhiteSpace(username)) { // Get logged on user var loggedOnUser = await context.MembershipUser.FirstOrDefaultAsync(x => x.UserName == username); if (loggedOnUser != null) { // Users role var loggedOnUsersRole = GetGroupMembershipRole(input.EntityToProcess.Topic.Group.Id, loggedOnUser); // Get the permissions and add to extendeddata as we'll use it again var permissions = _roleService.GetPermissions(input.EntityToProcess.Topic.Group, loggedOnUsersRole); input.ExtendedData.Add(Constants.ExtendedDataKeys.PermissionSet, permissions); // Check this users role has permission to create a post if (permissions[ForumConfiguration.Instance.PermissionDenyAccess].IsTicked || permissions[ForumConfiguration.Instance.PermissionReadOnly].IsTicked) { input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); } // Files? Check and then check permissions if (input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PostedFiles)) { if (permissions[ForumConfiguration.Instance.PermissionAttachFiles].IsTicked == false) { // Not allowed to upload files input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); } } // What if this is an edit if (existingPost != null) { if (existingPost.User.Id != loggedOnUser.Id && !permissions[ForumConfiguration.Instance.PermissionEditPosts].IsTicked) { // Not allowed to edit this post input.AddError(_localizationService.GetResourceString("Errors.NoPermission")); return(input); } } } else { input.AddError("Unable to get user from username"); return(input); } } else { input.AddError("Unable to get username"); return(input); } } catch (System.Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _favouriteService.RefreshContext(context); _pollService.RefreshContext(context); _postService.RefreshContext(context); _notificationService.RefreshContext(context); try { // Remove all notifications on this topic too if (input.EntityToProcess.TopicNotifications != null) { var notificationsToDelete = new List <TopicNotification>(); notificationsToDelete.AddRange(input.EntityToProcess.TopicNotifications); foreach (var topicNotification in notificationsToDelete) { input.EntityToProcess.TopicNotifications.Remove(topicNotification); _notificationService.Delete(topicNotification); } // Final Clear input.EntityToProcess.TopicNotifications.Clear(); } // Remove all favourites on this topic too if (input.EntityToProcess.Favourites != null) { var toDelete = new List <Favourite>(); toDelete.AddRange(input.EntityToProcess.Favourites); foreach (var entity in toDelete) { input.EntityToProcess.Favourites.Remove(entity); _favouriteService.Delete(entity); } // Final Clear input.EntityToProcess.Favourites.Clear(); } // Poll if (input.EntityToProcess.Poll != null) { var pollToDelete = input.EntityToProcess.Poll; // Final Clear input.EntityToProcess.Poll = null; // Delete the poll _pollService.Delete(pollToDelete); } // First thing - Set the last post as null and clear tags //input.EntityToProcess.Tags.Clear(); input.EntityToProcess.Tags = null; // Save here to clear the last post await context.SaveChangesAsync(); // Loop through all the posts and clear the associated entities // then delete the posts if (input.EntityToProcess.Posts != null) { var postsToDelete = new List <Post>(); postsToDelete.AddRange(input.EntityToProcess.Posts); foreach (var post in postsToDelete) { // Posts should only be deleted from this method as it clears // associated data var postDeleteResult = await _postService.Delete(post, true); if (!postDeleteResult.Successful) { input.AddError(postDeleteResult.ProcessLog.FirstOrDefault()); return(input); } } input.EntityToProcess.Posts.Clear(); // Clear last post input.EntityToProcess.LastPost = null; } // Finally delete the topic context.Topic.Remove(input.EntityToProcess); // Save here to clear the last post await context.SaveChangesAsync(); // Clear some caches _cacheService.ClearStartsWith("HotTopics"); } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <Topic> > Process(IPipelineProcess <Topic> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); _localizationService.RefreshContext(context); _spamService.RefreshContext(context); try { // Get the all the words I need var allWords = await context.BannedWord.ToListAsync(); var hasPollAnswers = input.ExtendedData.ContainsKey(Constants.ExtendedDataKeys.PollNewAnswers); var newPollAnswers = new List <PollAnswer>(); if (hasPollAnswers) { newPollAnswers = input.ExtendedData[Constants.ExtendedDataKeys.PollNewAnswers] as List <PollAnswer>; } // Do the stop words first foreach (var stopWord in allWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray()) { // Check name if (input.EntityToProcess.Name.IndexOf(stopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } // Check poll answers on entity or ones we are waiting to update if (input.EntityToProcess.Poll != null && input.EntityToProcess.Poll.PollAnswers.Any()) { foreach (var pollAnswer in input.EntityToProcess.Poll.PollAnswers) { if (input.EntityToProcess.Name.IndexOf(pollAnswer.Answer, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } if (hasPollAnswers) { if (newPollAnswers != null) { foreach (var pollAnswer in newPollAnswers) { if (input.EntityToProcess.Name.IndexOf(pollAnswer.Answer, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } } // Check tags if (input.EntityToProcess.Tags != null && input.EntityToProcess.Tags.Any()) { foreach (var topicTag in input.EntityToProcess.Tags) { if (input.EntityToProcess.Name.IndexOf(topicTag.Tag, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.AddError(_localizationService.GetResourceString("StopWord.Error")); return(input); } } } } // Check Akismet if (_spamService.IsSpam(input.EntityToProcess)) { input.EntityToProcess.Pending = true; input.ExtendedData.Add(Constants.ExtendedDataKeys.Moderate, true); } // Sanitise the banned words var bannedWords = allWords.Where(x => x.IsStopWord != true).Select(x => x.Word).ToArray(); // Topic name input.EntityToProcess.Name = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Name, bannedWords); // Sanitise Poll if (input.EntityToProcess.Poll != null && input.EntityToProcess.Poll.PollAnswers.Any()) { foreach (var pollAnswer in input.EntityToProcess.Poll.PollAnswers) { pollAnswer.Answer = _bannedWordService.SanitiseBannedWords(pollAnswer.Answer, bannedWords); } } // Santise new poll answers if (hasPollAnswers) { if (newPollAnswers != null) { foreach (var pollAnswer in newPollAnswers) { pollAnswer.Answer = _bannedWordService.SanitiseBannedWords(pollAnswer.Answer, bannedWords); } // Now re-assign them input.ExtendedData[Constants.ExtendedDataKeys.PollNewAnswers] = newPollAnswers; } } // Sanitise Tags if (input.EntityToProcess.Tags != null && input.EntityToProcess.Tags.Any()) { foreach (var topicTag in input.EntityToProcess.Tags) { topicTag.Tag = _bannedWordService.SanitiseBannedWords(topicTag.Tag, bannedWords); } } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } return(input); }
/// <inheritdoc /> public async Task <IPipelineProcess <MembershipUser> > Process(IPipelineProcess <MembershipUser> input, IMvcForumContext context) { _bannedWordService.RefreshContext(context); try { var email = input.EntityToProcess.Email; var userName = input.EntityToProcess.UserName; // Grab the email from the banned list var emailIsBanned = await context.BannedEmail.AnyAsync(x => x.Email == email); if (emailIsBanned == false) { // Email is ok, now check for banned words // Doesn't matter if it's a stop word or banned word, we'll reject it var allBannedWords = await context.BannedWord.ToListAsync(); var allStopWords = allBannedWords.Where(x => x.IsStopWord == true).Select(x => x.Word).ToArray(); // Loop banned Words foreach (var bannedWord in allBannedWords) { // Email if (email.ContainsCaseInsensitive(bannedWord.Word)) { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The email {email} contains a stop word"); return(input); } // Username if (userName.ContainsCaseInsensitive(bannedWord.Word)) { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The Username {userName} contains a stop word"); return(input); } } // Loop all stop words foreach (var allStopWord in allStopWords) { // Check for stop words if (input.EntityToProcess.Facebook != null && input.EntityToProcess.Facebook.IndexOf(allStopWord, StringComparison.CurrentCultureIgnoreCase) >= 0 || input.EntityToProcess.Location != null && input.EntityToProcess.Location.IndexOf(allStopWord, StringComparison.CurrentCultureIgnoreCase) >= 0 || input.EntityToProcess.Signature != null && input.EntityToProcess.Signature.IndexOf(allStopWord, StringComparison.CurrentCultureIgnoreCase) >= 0 || input.EntityToProcess.Twitter != null && input.EntityToProcess.Twitter.IndexOf(allStopWord, StringComparison.CurrentCultureIgnoreCase) >= 0 || input.EntityToProcess.Website != null && input.EntityToProcess.Website.IndexOf(allStopWord, StringComparison.CurrentCultureIgnoreCase) >= 0) { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The Username {userName} contains a stop word"); } } // Santise the fields now var justBannedWord = allBannedWords.Where(x => x.IsStopWord == false).Select(x => x.Word).ToArray(); // Sanitised input.EntityToProcess.Facebook = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Facebook, justBannedWord); input.EntityToProcess.Location = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Location, justBannedWord); input.EntityToProcess.Signature = _bannedWordService.SanitiseBannedWords(StringUtils.ScrubHtml(input.EntityToProcess.Signature, true), justBannedWord); input.EntityToProcess.Twitter = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Twitter, justBannedWord); input.EntityToProcess.Website = _bannedWordService.SanitiseBannedWords(input.EntityToProcess.Website, justBannedWord); } else { input.Successful = false; input.ProcessLog.Clear(); input.ProcessLog.Add($"The email {email} is banned"); } } catch (Exception ex) { input.AddError(ex.Message); _loggingService.Error(ex); } if (input.Successful) { input.ProcessLog.Add("CheckBannedWordsPipe completed successfully"); } return(input); }