public void Delete_Post_Removed_From_TopicList_And_Last_Post() { var postRepository = Substitute.For<IPostRepository>(); var topicRepository = Substitute.For<ITopicRepository>(); var roleService = Substitute.For<IRoleService>(); var membershipUserPointsService = Substitute.For<IMembershipUserPointsService>(); var settingsService = Substitute.For<ISettingsService>(); var localisationService = Substitute.For<ILocalizationService>(); var postService = new PostService(membershipUserPointsService, settingsService, roleService, postRepository, topicRepository, localisationService, _api); // Create topic var topic = new Topic { Name = "Captain America"}; // Create some posts with one to delete var postToDelete = new Post { Id = Guid.NewGuid(), Topic = topic, IsTopicStarter = false, DateCreated = DateTime.UtcNow}; var postToStay = new Post { Id = Guid.NewGuid(), Topic = topic, IsTopicStarter = false, DateCreated = DateTime.UtcNow.Subtract(TimeSpan.FromDays(2)) }; var postToStayTwo = new Post { Id = Guid.NewGuid(), Topic = topic, IsTopicStarter = false, DateCreated = DateTime.UtcNow.Subtract(TimeSpan.FromDays(3)) }; // set last post topic.LastPost = postToDelete; // Set the post list to the topic var posts = new List<Post> {postToDelete, postToStay, postToStayTwo}; topic.Posts = posts; // Save postService.Delete(postToDelete); // Test that settings is no longer in cache Assert.IsTrue(topic.LastPost == postToStay); Assert.IsTrue(topic.Posts.Count == 2); }
/// <summary> /// Check whether a topic is spam or not /// </summary> /// <param name="topic"></param> /// <returns></returns> public bool IsSpam(Topic topic) { // If akisment is is not enable always return false if (_settingsService.GetSettings().EnableAkisment == null || _settingsService.GetSettings().EnableAkisment == false) return false; // Akisment must be enabled var firstOrDefault = topic.Posts.FirstOrDefault(x => x.IsTopicStarter); if (firstOrDefault != null) { var comment = new Comment { blog = StringUtils.CheckLinkHasHttp(_settingsService.GetSettings().ForumUrl), comment_type = "comment", comment_author = topic.User.UserName, comment_author_email = topic.User.Email, comment_content = firstOrDefault.PostContent, permalink = String.Empty, referrer = HttpContext.Current.Request.ServerVariables["HTTP_REFERER"], user_agent = HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"], user_ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] }; var validator = new Validator(_settingsService.GetSettings().AkismentKey); return validator.IsSpam(comment); } return true; }
public IList<TopicNotification> GetByTopic(Topic topic) { return _context.TopicNotification .Where(x => x.Topic.Id == topic.Id) .AsNoTracking() .ToList(); }
public void Delete_Topic_Deleted_If_Topic_Starter() { var postRepository = Substitute.For<IPostRepository>(); var topicRepository = Substitute.For<ITopicRepository>(); var roleService = Substitute.For<IRoleService>(); var membershipUserPointsService = Substitute.For<IMembershipUserPointsService>(); var settingsService = Substitute.For<ISettingsService>(); var localisationService = Substitute.For<ILocalizationService>(); var postService = new PostService(membershipUserPointsService, settingsService, roleService, postRepository, topicRepository, localisationService, _api); var tags = new List<TopicTag> { new TopicTag{Tag = "Thor"}, new TopicTag{Tag = "Gambit"} }; var topic = new Topic { Name = "Captain America", Tags = tags }; var post = new Post { Id = Guid.NewGuid(), Topic = topic, IsTopicStarter = true}; topic.LastPost = post; topic.Posts = new List<Post>(); post.IsTopicStarter = true; topic.Posts.Add(post); // Save var deleteTopic = postService.Delete(post); Assert.IsTrue(deleteTopic); }
public void AddPost() { var postRepository = Substitute.For<IPostRepository>(); var topicRepository = Substitute.For<ITopicRepository>(); var roleService = Substitute.For<IRoleService>(); var membershipUserPointsService = Substitute.For<IMembershipUserPointsService>(); var settingsService = Substitute.For<ISettingsService>(); settingsService.GetSettings().Returns(new Settings { PointsAddedPerPost = 20 }); var localisationService = Substitute.For<ILocalizationService>(); var postService = new PostService(membershipUserPointsService, settingsService, roleService, postRepository, topicRepository, localisationService, _api); var category = new Category(); var role = new MembershipRole{RoleName = "TestRole"}; var categoryPermissionForRoleSet = new List<CategoryPermissionForRole> { new CategoryPermissionForRole { Permission = new Permission { Name = AppConstants.PermissionEditPosts }, IsTicked = true}, new CategoryPermissionForRole { Permission = new Permission { Name = AppConstants.PermissionDenyAccess }, IsTicked = false}, new CategoryPermissionForRole { Permission = new Permission { Name = AppConstants.PermissionReadOnly }, IsTicked = false} }; var permissionSet = new PermissionSet(categoryPermissionForRoleSet); roleService.GetPermissions(category, role).Returns(permissionSet); var topic = new Topic { Name = "Captain America", Category = category}; var user = new MembershipUser { UserName = "******", Roles = new List<MembershipRole>{role} }; var newPost = postService.AddNewPost("A test post", topic, user, out permissionSet); Assert.AreEqual(newPost.User, user); Assert.AreEqual(newPost.Topic, topic); }
/// <summary> /// Add a new post /// </summary> /// <param name="postContent"> </param> /// <param name="topic"> </param> /// <param name="user"></param> /// <param name="permissions"> </param> /// <returns>True if post added</returns> public Post AddNewPost(string postContent, Topic topic, MembershipUser user, out PermissionSet permissions) { // Get the permissions for the category that this topic is in permissions = _roleService.GetPermissions(topic.Category, UsersRole(user)); // Check this users role has permission to create a post if (permissions[AppConstants.PermissionDenyAccess].IsTicked || permissions[AppConstants.PermissionReadOnly].IsTicked) { // Throw exception so Ajax caller picks it up throw new ApplicationException(_localizationService.GetResourceString("Errors.NoPermission")); } // Has permission so create the post var newPost = new Post { PostContent = postContent, User = user, Topic = topic, IpAddress = StringUtils.GetUsersIpAddress(), DateCreated = DateTime.UtcNow, DateEdited = DateTime.UtcNow }; // Sort the search field out var category = topic.Category; if (category.ModeratePosts == true) { newPost.Pending = true; } var e = new PostMadeEventArgs { Post = newPost }; EventManager.Instance.FireBeforePostMade(this, e); if (!e.Cancel) { // create the post Add(newPost); // Update the users points score and post count for posting _membershipUserPointsService.Add(new MembershipUserPoints { Points = _settingsService.GetSettings().PointsAddedPerPost, User = user, PointsFor = PointsFor.Post, PointsForId = newPost.Id }); // add the last post to the topic topic.LastPost = newPost; EventManager.Instance.FireAfterPostMade(this, new PostMadeEventArgs { Post = newPost }); return newPost; } return newPost; }
public void Update(Topic item) { // Check there's not an object with same identifier already in context if (_context.Topic.Local.Select(x => x.Id == item.Id).Any()) { throw new ApplicationException("Object already exists in context - you do not need to call Update. Save occurs on Commit"); } _context.Entry(item).State = EntityState.Modified; }
public IList<TopicNotification> GetByUserAndTopic(MembershipUser user, Topic topic, bool addTracking = false) { var notifications = _context.TopicNotification .Where(x => x.User.Id == user.Id && x.Topic.Id == topic.Id); if (addTracking) { return notifications.ToList(); } return notifications.AsNoTracking().ToList(); }
/// <summary> /// Create a new topic and also the topic starter post /// </summary> /// <param name="topic"></param> /// <returns></returns> public Topic Add(Topic topic) { topic = SanitizeTopic(topic); topic.CreateDate = DateTime.UtcNow; // url slug generator topic.Slug = ServiceHelpers.GenerateSlug(topic.Name, _topicRepository.GetTopicBySlugLike(ServiceHelpers.CreateUrl(topic.Name)), null); return _topicRepository.Add(topic); }
/// <summary> /// Add a new post /// </summary> /// <param name="postContent"> </param> /// <param name="topic"> </param> /// <param name="user"></param> /// <param name="permissions"> </param> /// <returns>True if post added</returns> public Post AddNewPost(string postContent, Topic topic, MembershipUser user, out PermissionSet permissions) { // Get the permissions for the category that this topic is in permissions = _roleService.GetPermissions(topic.Category, UsersRole(user)); // Check this users role has permission to create a post if (permissions[AppConstants.PermissionDenyAccess].IsTicked || permissions[AppConstants.PermissionReadOnly].IsTicked) { // Throw exception so Ajax caller picks it up throw new ApplicationException(_localizationService.GetResourceString("Errors.NoPermission")); } // Has permission so create the post var newPost = new Post { PostContent = postContent, User = user, Topic = topic, IpAddress = StringUtils.GetUsersIpAddress() }; newPost = SanitizePost(newPost); var e = new PostMadeEventArgs { Post = newPost, Api = _api }; EventManager.Instance.FireBeforePostMade(this, e); if (!e.Cancel) { // create the post Add(newPost); // Update the users points score and post count for posting _membershipUserPointsService.Add(new MembershipUserPoints { Points = _settingsService.GetSettings().PointsAddedPerPost, User = user }); // add the last post to the topic topic.LastPost = newPost; // Removed as its updated via the commit //_topicRepository.Update(topic); EventManager.Instance.FireAfterPostMade(this, new PostMadeEventArgs { Post = newPost, Api = _api }); return newPost; } return newPost; }
/// <summary> /// Maps the posts for a specific topic /// </summary> /// <param name="posts"></param> /// <param name="votes"></param> /// <param name="permission"></param> /// <param name="topic"></param> /// <param name="loggedOnUser"></param> /// <param name="settings"></param> /// <param name="favourites"></param> /// <returns></returns> public static List<PostViewModel> CreatePostViewModels(IEnumerable<Post> posts, List<Vote> votes, PermissionSet permission, Topic topic, MembershipUser loggedOnUser, Settings settings, List<Favourite> favourites) { var viewModels = new List<PostViewModel>(); var groupedVotes = votes.ToLookup(x => x.Post.Id); var groupedFavourites = favourites.ToLookup(x => x.Post.Id); foreach (var post in posts) { var id = post.Id; var postVotes = (groupedVotes.Contains(id) ? groupedVotes[id].ToList() : new List<Vote>()); var postFavs = (groupedFavourites.Contains(id) ? groupedFavourites[id].ToList() : new List<Favourite>()); viewModels.Add(CreatePostViewModel(post, postVotes, permission, topic, loggedOnUser, settings, postFavs)); } return viewModels; }
/// <summary> /// Add new tags to a topic, ignore existing ones /// </summary> /// <param name="tags"></param> /// <param name="topic"></param> public void Add(string tags, Topic topic) { if(!string.IsNullOrEmpty(tags)) { tags = StringUtils.SafePlainText(tags); var splitTags = tags.Replace(" ", "").Split(','); if(topic.Tags == null) { topic.Tags = new List<TopicTag>(); } var newTagNames = splitTags.Select(tag => tag); var newTags = new List<TopicTag>(); var existingTags = new List<TopicTag>(); foreach (var newTag in newTagNames.Distinct()) { var tag = _tagRepository.GetTagName(newTag); if (tag != null) { // Exists existingTags.Add(tag); } else { // Doesn't exists var nTag = new TopicTag { Tag = newTag, Slug = ServiceHelpers.CreateUrl(newTag) }; _tagRepository.Add(nTag); newTags.Add(nTag); } } newTags.AddRange(existingTags); topic.Tags = newTags; // Fire the tag badge check _badgeService.ProcessBadge(BadgeType.Tag, topic.User); } }
public PartialViewResult GetTopicBreadcrumb(Topic topic) { var category = topic.Category; using (UnitOfWorkManager.NewUnitOfWork()) { var viewModel = new BreadcrumbViewModel { Categories = _categoryService.GetCategoryParents(category).ToList(), Topic = topic }; if (!viewModel.Categories.Any()) { viewModel.Categories.Add(topic.Category); } return PartialView("GetCategoryBreadcrumb", viewModel); } }
public void Add_Test() { const string tag = "testtag"; var tagRepository = Substitute.For<ITopicTagRepository>(); var topicRepository = Substitute.For<ITopicRepository>(); var topicTagService = new TopicTagService(tagRepository, topicRepository); tagRepository.GetTagName(tag).Returns(x => null); var topic = new Topic(); topicTagService.Add(tag, topic); Assert.IsTrue(topic.Tags.Count() == 1); Assert.IsTrue(topic.Tags[0].Tag == tag); tagRepository.Received().Add(Arg.Is<TopicTag>(x => x.Tag == tag)); }
public void Add_Test_With_No_Existing_Tags() { const string testtag = "testtag"; const string testtagtwo = "testtagtwo"; const string andthree = "andthree"; var tagRepository = Substitute.For<ITopicTagRepository>(); var topicRepository = Substitute.For<ITopicRepository>(); var topicTagService = new TopicTagService(tagRepository, topicRepository); tagRepository.GetTagName(testtag).Returns(x => new TopicTag { Tag = testtag }); tagRepository.GetTagName(testtagtwo).Returns(x => new TopicTag { Tag = testtagtwo }); tagRepository.GetTagName(andthree).Returns(x => new TopicTag { Tag = andthree }); var topic = new Topic(); topicTagService.Add(string.Concat(testtag, " , ", testtagtwo, " , ", andthree), topic); Assert.IsTrue(topic.Tags.Count() == 3); tagRepository.DidNotReceive().Add(Arg.Is<TopicTag>(x => x.Tag == testtag)); tagRepository.DidNotReceive().Add(Arg.Is<TopicTag>(x => x.Tag == testtagtwo)); tagRepository.DidNotReceive().Add(Arg.Is<TopicTag>(x => x.Tag == andthree)); }
/// <summary> /// Add a last post to a topic. Must be part of a separate database update /// in EF because of circular dependencies. So save the topic before calling this. /// </summary> /// <param name="topic"></param> /// <param name="postContent"></param> /// <returns></returns> public Post AddLastPost(Topic topic, string postContent) { topic = SanitizeTopic(topic); // Create the post var post = new Post { DateCreated = DateTime.UtcNow, IsTopicStarter = true, DateEdited = DateTime.UtcNow, PostContent = StringUtils.GetSafeHtml(postContent), User = topic.User, Topic = topic }; // Add the post _postRepository.Add(post); topic.LastPost = post; return post; }
public void Delete_Check_Tags_Are_Cleared() { var topicRepository = Substitute.For<ITopicRepository>(); var postRepository = Substitute.For<IPostRepository>(); var membershipUserPointsService = Substitute.For<IMembershipUserPointsService>(); var settingsService = Substitute.For<ISettingsService>(); var topicService = new TopicService(membershipUserPointsService, settingsService, topicRepository, postRepository, _api, _topicNotificationService); var topic = new Topic { Name = "something", Tags = new List<TopicTag> { new TopicTag{Tag = "tagone"}, new TopicTag{Tag = "tagtwo"} } }; topicService.Delete(topic); Assert.IsTrue(!topic.Tags.Any()); }
public static PostViewModel CreatePostViewModel(Post post, List<Vote> votes, PermissionSet permission, Topic topic, MembershipUser loggedOnUser, Settings settings, List<Favourite> favourites) { var allowedToVote = (loggedOnUser != null && loggedOnUser.Id != post.User.Id && loggedOnUser.TotalPoints > settings.PointsAllowedToVoteAmount && votes.All(x => x.User.Id != loggedOnUser.Id)); var hasFavourited = false; if (loggedOnUser != null && loggedOnUser.Id != post.User.Id) { hasFavourited = favourites.Any(x => x.Member.Id == loggedOnUser.Id); } return new PostViewModel { Permissions = permission, Votes = votes, Post = post, ParentTopic = topic, AllowedToVote = allowedToVote, MemberHasFavourited = hasFavourited, Favourites = favourites, PermaLink = string.Concat(topic.NiceUrl, "?", AppConstants.PostOrderBy, "=", AppConstants.AllPosts, "#comment-", post.Id) }; }
public static PostViewModel CreatePostViewModel(Post post, List<Vote> votes, PermissionSet permission, Topic topic, MembershipUser loggedOnUser, Settings settings, List<Favourite> favourites) { var allowedToVote = (loggedOnUser != null && loggedOnUser.Id != post.User.Id && loggedOnUser.TotalPoints >= settings.PointsAllowedToVoteAmount); // Remove votes where no VotedBy has been recorded votes.RemoveAll(x => x.VotedByMembershipUser == null); var hasVotedUp = false; var hasVotedDown = false; var hasFavourited = false; if (loggedOnUser != null && loggedOnUser.Id != post.User.Id) { hasFavourited = favourites.Any(x => x.Member.Id == loggedOnUser.Id); hasVotedUp = votes.Count(x => x.Amount > 0 && x.VotedByMembershipUser.Id == loggedOnUser.Id) > 0; hasVotedDown = votes.Count(x => x.Amount < 0 && x.VotedByMembershipUser.Id == loggedOnUser.Id) > 0; } // Check for online status var date = DateTime.UtcNow.AddMinutes(-AppConstants.TimeSpanInMinutesToShowMembers); return new PostViewModel { Permissions = permission, Votes = votes, Post = post, ParentTopic = topic, AllowedToVote = allowedToVote, MemberHasFavourited = hasFavourited, Favourites = favourites, PermaLink = string.Concat(topic.NiceUrl, "?", AppConstants.PostOrderBy, "=", AppConstants.AllPosts, "#comment-", post.Id), MemberIsOnline = post.User.LastActivityDate > date, HasVotedDown = hasVotedDown, HasVotedUp = hasVotedUp }; }
public ActionResult MovePost(MovePostViewModel viewModel) { using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork()) { // Firstly check if this is a post and they are allowed to move it var post = _postService.Get(viewModel.PostId); if (post == null) { return ErrorToHomePage(LocalizationService.GetResourceString("Errors.GenericMessage")); } var permissions = RoleService.GetPermissions(post.Topic.Category, UsersRole); var allowedCategories = _categoryService.GetAllowedCategories(UsersRole); // Does the user have permission to this posts category var cat = allowedCategories.FirstOrDefault(x => x.Id == post.Topic.Category.Id); if (cat == null) { return ErrorToHomePage(LocalizationService.GetResourceString("Errors.NoPermission")); } // Does this user have permission to move if (!permissions[SiteConstants.Instance.PermissionEditPosts].IsTicked) { return NoPermission(post.Topic); } var previousTopic = post.Topic; var category = post.Topic.Category; var postCreator = post.User; Topic topic; var cancelledByEvent = false; // If the dropdown has a value, then we choose that first if (viewModel.TopicId != null) { // Get the selected topic topic = _topicService.Get((Guid) viewModel.TopicId); } else if(!string.IsNullOrEmpty(viewModel.TopicTitle)) { // We get the banned words here and pass them in, so its just one call // instead of calling it several times and each call getting all the words back var bannedWordsList = _bannedWordService.GetAll(); List<string> bannedWords = null; if (bannedWordsList.Any()) { bannedWords = bannedWordsList.Select(x => x.Word).ToList(); } // Create the topic topic = new Topic { Name = _bannedWordService.SanitiseBannedWords(viewModel.TopicTitle, bannedWords), Category = category, User = postCreator }; // Create the topic topic = _topicService.Add(topic); // Save the changes unitOfWork.SaveChanges(); // Set the post to be a topic starter post.IsTopicStarter = true; // Check the Events var e = new TopicMadeEventArgs { Topic = topic }; EventManager.Instance.FireBeforeTopicMade(this, e); if (e.Cancel) { cancelledByEvent = true; ShowMessage(new GenericMessageViewModel { MessageType = GenericMessages.warning, Message = LocalizationService.GetResourceString("Errors.GenericMessage") }); } } else { // No selected topic OR topic title, just redirect back to the topic return Redirect(post.Topic.NiceUrl); } // If this create was cancelled by an event then don't continue if (!cancelledByEvent) { // Now update the post to the new topic post.Topic = topic; // Also move any posts, which were in reply to this post if (viewModel.MoveReplyToPosts) { var relatedPosts = _postService.GetReplyToPosts(viewModel.PostId); foreach (var relatedPost in relatedPosts) { relatedPost.Topic = topic; } } unitOfWork.SaveChanges(); // 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; try { unitOfWork.Commit(); EventManager.Instance.FireAfterTopicMade(this, new TopicMadeEventArgs { Topic = topic }); // On Update redirect to the topic return RedirectToAction("Show", "Topic", new { slug = topic.Slug }); } catch (Exception ex) { unitOfWork.Rollback(); LoggingService.Error(ex); ShowMessage(new GenericMessageViewModel { Message = ex.Message, MessageType = GenericMessages.danger }); } } // Repopulate the topics var topics = _topicService.GetAllSelectList(allowedCategories, 30); topics.Insert(0, new SelectListItem { Text = LocalizationService.GetResourceString("Topic.Choose"), Value = "" }); viewModel.LatestTopics = topics; viewModel.Post = ViewModelMapping.CreatePostViewModel(post, post.Votes.ToList(), permissions, post.Topic, LoggedOnReadOnlyUser, SettingsService.GetSettings(), post.Favourites.ToList()); viewModel.Post.MinimalPost = true; viewModel.PostId = post.Id; return View(viewModel); } }
private void NotifyNewTopics(Topic topic, IUnitOfWork unitOfWork) { try { // Get all notifications for this category var notifications = _topicNotificationService.GetByTopic(topic).Select(x => x.User.Id).ToList(); if (notifications.Any()) { // remove the current user from the notification, don't want to notify yourself that you // have just made a topic! notifications.Remove(LoggedOnReadOnlyUser.Id); if (notifications.Count > 0) { // Now get all the users that need notifying var usersToNotify = MembershipService.GetUsersById(notifications); // Create the email var sb = new StringBuilder(); sb.AppendFormat("<p>{0}</p>", string.Format(LocalizationService.GetResourceString("Post.Notification.NewPosts"), topic.Name)); sb.Append(AppHelpers.ConvertPostContent(topic.LastPost.PostContent)); sb.AppendFormat("<p><a href=\"{0}\">{0}</a></p>", string.Concat(SettingsService.GetSettings().ForumUrl.TrimEnd('/'), topic.NiceUrl)); // create the emails only to people who haven't had notifications disabled var emails = usersToNotify.Where(x => x.DisableEmailNotifications != true && !x.IsLockedOut).Select(user => new Email { Body = _emailService.EmailTemplate(user.UserName, sb.ToString()), EmailTo = user.Email, NameTo = user.UserName, Subject = string.Concat(LocalizationService.GetResourceString("Post.Notification.Subject"), SettingsService.GetSettings().ForumName) }).ToList(); // and now pass the emails in to be sent _emailService.SendMail(emails); unitOfWork.Commit(); } } } catch (Exception ex) { unitOfWork.Rollback(); LoggingService.Error(ex); } }
private ActionResult NoPermission(Topic topic) { // Trying to be a sneaky mo fo, so tell them TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Errors.NoPermission"), MessageType = GenericMessages.danger }; return Redirect(topic.NiceUrl); }
/// <summary> /// Delete a topic /// </summary> /// <param name="topic"></param> public void Delete(Topic topic) { topic.LastPost = null; topic.Tags.Clear(); // Delete all posts if (topic.Posts != null) { var postsToDelete = new List<Post>(); postsToDelete.AddRange(topic.Posts); foreach (var post in postsToDelete) { _postRepository.Delete(post); } } if (topic.TopicNotifications != null) { var notificationsToDelete = new List<TopicNotification>(); notificationsToDelete.AddRange(topic.TopicNotifications); foreach (var topicNotification in notificationsToDelete) { _topicNotificationService.Delete(topicNotification); } } _topicRepository.Delete(topic); }
/// <summary> /// Mark a topic as solved /// </summary> /// <param name="topic"></param> /// <param name="post"></param> /// <param name="marker"></param> /// <param name="solutionWriter"></param> /// <returns>True if topic has been marked as solved</returns> public bool SolveTopic(Topic topic, Post post, MembershipUser marker, MembershipUser solutionWriter) { var solved = false; var e = new MarkedAsSolutionEventArgs { Topic = topic, Post = post, Marker = marker, SolutionWriter = solutionWriter }; EventManager.Instance.FireBeforeMarkedAsSolution(this, e); if (!e.Cancel) { // Make sure this user owns the topic, if not do nothing if (topic.User.Id == marker.Id) { // Update the post post.IsSolution = true; //_postRepository.Update(post); // Update the topic topic.Solved = true; //SaveOrUpdate(topic); // Assign points // Do not give points to the user if they are marking their own post as the solution if (marker.Id != solutionWriter.Id) { _membershipUserPointsService.Add(new MembershipUserPoints { Points = _settingsService.GetSettings().PointsAddedForSolution, User = solutionWriter }); } EventManager.Instance.FireAfterMarkedAsSolution(this, new MarkedAsSolutionEventArgs { Topic = topic, Post = post, Marker = marker, SolutionWriter = solutionWriter }); solved = true; } } return solved; }
public Topic SanitizeTopic(Topic topic) { topic.Name = StringUtils.SafePlainText(topic.Name); return topic; }
public ActionResult UploadPostFiles(AttachFileToPostViewModel attachFileToPostViewModel) { using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork()) { var topic = new Topic(); try { // First this to do is get the post var post = _postService.Get(attachFileToPostViewModel.UploadPostId); if (post != null) { // Now get the topic topic = post.Topic; // Check we get a valid post back and have some file if (attachFileToPostViewModel.Files != null && attachFileToPostViewModel.Files.Any()) { // Now get the category var category = topic.Category; // Get the permissions for this category, and check they are allowed to update and // not trying to be a sneaky mofo var permissions = RoleService.GetPermissions(category, UsersRole); if (permissions[AppConstants.PermissionAttachFiles].IsTicked == false || LoggedOnReadOnlyUser.DisableFileUploads == true) { TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Errors.NoPermission"), MessageType = GenericMessages.danger }; return Redirect(topic.NiceUrl); } // woot! User has permission and all seems ok // Before we save anything, check the user already has an upload folder and if not create one var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(SiteConstants.UploadFolderPath, LoggedOnReadOnlyUser.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 attachFileToPostViewModel.Files) { if (file != null) { // If successful then upload the file var uploadResult = AppHelpers.UploadFile(file, uploadFolderPath, LocalizationService); if (!uploadResult.UploadSuccessful) { TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = uploadResult.ErrorMessage, MessageType = GenericMessages.danger }; return Redirect(topic.NiceUrl); } // Add the filename to the database var loggedOnUser = MembershipService.GetUser(LoggedOnReadOnlyUser.Id); var uploadedFile = new UploadedFile { Filename = uploadResult.UploadedFileName, Post = post, MembershipUser = loggedOnUser }; _uploadedFileService.Add(uploadedFile); } } //Commit unitOfWork.Commit(); // Redirect to the topic with a success message TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Post.FilesUploaded"), MessageType = GenericMessages.success }; return Redirect(topic.NiceUrl); } // Else return with error to home page return topic != null ? Redirect(topic.NiceUrl) : ErrorToHomePage(LocalizationService.GetResourceString("Errors.GenericMessage")); } // Else return with error to home page return ErrorToHomePage(LocalizationService.GetResourceString("Errors.GenericMessage")); } catch (Exception ex) { unitOfWork.Rollback(); LoggingService.Error(ex); TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Errors.GenericMessage"), MessageType = GenericMessages.danger }; return topic != null ? Redirect(topic.NiceUrl) : ErrorToHomePage(LocalizationService.GetResourceString("Errors.GenericMessage")); } } }
/// <summary> /// Delete a topic /// </summary> /// <param name="topic"></param> /// <param name="unitOfWork"></param> public void Delete(Topic topic, IUnitOfWork unitOfWork) { // First thing - Set the last post as null and clear tags topic.LastPost = null; topic.Tags.Clear(); // Save here to clear the last post unitOfWork.SaveChanges(); // TODO - Need to refactor as some of the code below is duplicated in the post delete // Loop through all the posts and clear the associated entities // then delete the posts if (topic.Posts != null) { var postsToDelete = new List<Post>(); postsToDelete.AddRange(topic.Posts); foreach (var post in postsToDelete) { // Posts should only be deleted from this method as it clears // associated data _postService.Delete(post, unitOfWork, true); } // Final clear topic.Posts.Clear(); } unitOfWork.SaveChanges(); // Remove all notifications on this topic too if (topic.TopicNotifications != null) { var notificationsToDelete = new List<TopicNotification>(); notificationsToDelete.AddRange(topic.TopicNotifications); foreach (var topicNotification in notificationsToDelete) { _topicNotificationService.Delete(topicNotification); } // Final Clear topic.TopicNotifications.Clear(); } // Remove all favourites on this topic too if (topic.Favourites != null) { var toDelete = new List<Favourite>(); toDelete.AddRange(topic.Favourites); foreach (var entity in toDelete) { _favouriteService.Delete(entity); } // Final Clear topic.Favourites.Clear(); } // Poll if (topic.Poll != null) { //Delete the poll answers var pollAnswers = topic.Poll.PollAnswers; if (pollAnswers.Any()) { var pollAnswersList = new List<PollAnswer>(); pollAnswersList.AddRange(pollAnswers); foreach (var answer in pollAnswersList) { answer.Poll = null; _pollAnswerService.Delete(answer); } } topic.Poll.PollAnswers.Clear(); topic.Poll.User = null; _pollService.Delete(topic.Poll); // Final Clear topic.Poll = null; } // Finally delete the topic _context.Topic.Remove(topic); }
/// <summary> /// Add a last post to a topic. Must be part of a separate database update /// in EF because of circular dependencies. So save the topic before calling this. /// </summary> /// <param name="topic"></param> /// <param name="postContent"></param> /// <returns></returns> public Post AddLastPost(Topic topic, string postContent) { topic = SanitizeTopic(topic); // Create the post var post = new Post { DateCreated = DateTime.UtcNow, IsTopicStarter = true, DateEdited = DateTime.UtcNow, PostContent = postContent, User = topic.User, Topic = topic }; // Add the post _postService.Add(post); topic.LastPost = post; return post; }
public IList<TopicNotification> GetByUserAndTopic(MembershipUser user, Topic topic) { return _context.TopicNotification .Where(x => x.User.Id == user.Id && x.Topic.Id == topic.Id) .ToList(); }
public ActionResult Create(CreateEditTopicViewModel topicViewModel) { // Get the category var category = _categoryService.Get(topicViewModel.Category); // First check this user is allowed to create topics in this category var permissions = RoleService.GetPermissions(category, UsersRole); // Now we have the category and permissionSet - Populate the optional permissions // This is just in case the viewModel is return back to the view also sort the allowedCategories var allowedCategories = _categoryService.GetAllowedCategories(UsersRole); topicViewModel.OptionalPermissions = GetCheckCreateTopicPermissions(permissions); topicViewModel.Categories = GetBaseSelectListCategories(allowedCategories); topicViewModel.IsTopicStarter = true; if (topicViewModel.PollAnswers == null) { topicViewModel.PollAnswers = new List<PollAnswer>(); } /*---- End Re-populate ViewModel ----*/ // Check stop words var stopWords = _bannedWordService.GetAll(true); foreach (var stopWord in stopWords) { if (topicViewModel.Content.IndexOf(stopWord.Word, StringComparison.CurrentCultureIgnoreCase) >= 0 || topicViewModel.Name.IndexOf(stopWord.Word, StringComparison.CurrentCultureIgnoreCase) >= 0) { ShowMessage(new GenericMessageViewModel { Message = LocalizationService.GetResourceString("StopWord.Error"), MessageType = GenericMessages.danger }); // Ahhh found a stop word. Abandon operation captain. return View(topicViewModel); } } if (ModelState.IsValid) { // Quick check to see if user is locked out, when logged in if (LoggedOnUser.IsLockedOut || LoggedOnUser.DisablePosting == true || !LoggedOnUser.IsApproved) { FormsAuthentication.SignOut(); return ErrorToHomePage(LocalizationService.GetResourceString("Errors.NoAccess")); } var successfullyCreated = false; var moderate = false; var topic = new Topic(); using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork()) { // Check this users role has permission to create a post if (permissions[AppConstants.PermissionDenyAccess].IsTicked || permissions[AppConstants.PermissionReadOnly].IsTicked || !permissions[AppConstants.PermissionCreateTopics].IsTicked) { // Add a model error that the user has no permissions ModelState.AddModelError(string.Empty, LocalizationService.GetResourceString("Errors.NoPermission")); } else { // We get the banned words here and pass them in, so its just one call // instead of calling it several times and each call getting all the words back var bannedWordsList = _bannedWordService.GetAll(); List<string> bannedWords = null; if (bannedWordsList.Any()) { bannedWords = bannedWordsList.Select(x => x.Word).ToList(); } // Create the topic model topic = new Topic { Name = _bannedWordService.SanitiseBannedWords(topicViewModel.Name, bannedWords), Category = category, User = LoggedOnUser }; // Check Permissions for topic topions if (permissions[AppConstants.PermissionLockTopics].IsTicked) { topic.IsLocked = topicViewModel.IsLocked; } if (permissions[AppConstants.PermissionCreateStickyTopics].IsTicked) { topic.IsSticky = topicViewModel.IsSticky; } // See if the user has actually added some content to the topic if (!string.IsNullOrEmpty(topicViewModel.Content)) { // Check for any banned words topicViewModel.Content = _bannedWordService.SanitiseBannedWords(topicViewModel.Content, bannedWords); // See if this is a poll and add it to the topic if (topicViewModel.PollAnswers.Count(x => x != null) > 0) { // Do they have permission to create a new poll if (permissions[AppConstants.PermissionCreatePolls].IsTicked) { // Create a new Poll var newPoll = new Poll { User = LoggedOnUser }; // Create the poll _pollService.Add(newPoll); // Save the poll in the context so we can add answers unitOfWork.SaveChanges(); // Now sort the answers var newPollAnswers = new List<PollAnswer>(); foreach (var pollAnswer in topicViewModel.PollAnswers) { if (pollAnswer.Answer != null) { // Attach newly created poll to each answer pollAnswer.Poll = newPoll; _pollAnswerService.Add(pollAnswer); newPollAnswers.Add(pollAnswer); } } // Attach answers to poll newPoll.PollAnswers = newPollAnswers; // Save the new answers in the context unitOfWork.SaveChanges(); // Add the poll to the topic topic.Poll = newPoll; } else { //No permission to create a Poll so show a message but create the topic TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Errors.NoPermissionPolls"), MessageType = GenericMessages.info }; } } // Update the users points score for posting _membershipUserPointsService.Add(new MembershipUserPoints { Points = SettingsService.GetSettings().PointsAddedPerPost, User = LoggedOnUser }); // Check for moderation if (category.ModerateTopics == true) { topic.Pending = true; moderate = true; } // Create the topic topic = _topicService.Add(topic); // Save the changes unitOfWork.SaveChanges(); // Now create and add the post to the topic var topicPost = _topicService.AddLastPost(topic, topicViewModel.Content); // Now check its not spam var akismetHelper = new AkismetHelper(SettingsService); if (!akismetHelper.IsSpam(topic)) { if (topicViewModel.Files != null) { // Get the permissions for this category, and check they are allowed to update if (permissions[AppConstants.PermissionAttachFiles].IsTicked && LoggedOnUser.DisableFileUploads != true) { // woot! User has permission and all seems ok // Before we save anything, check the user already has an upload folder and if not create one var uploadFolderPath = HostingEnvironment.MapPath(string.Concat(SiteConstants.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 topicViewModel.Files) { if (file != null) { // If successful then upload the file var uploadResult = AppHelpers.UploadFile(file, uploadFolderPath, LocalizationService); if (!uploadResult.UploadSuccessful) { TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = uploadResult.ErrorMessage, MessageType = GenericMessages.danger }; unitOfWork.Rollback(); return View(topicViewModel); } // Add the filename to the database var uploadedFile = new UploadedFile { Filename = uploadResult.UploadedFileName, Post = topicPost, MembershipUser = LoggedOnUser }; _uploadedFileService.Add(uploadedFile); } } } } // Add the tags if any too if (!string.IsNullOrEmpty(topicViewModel.Tags)) { // Sanitise the tags topicViewModel.Tags = _bannedWordService.SanitiseBannedWords(topicViewModel.Tags, bannedWords); // Now add the tags _topicTagService.Add(topicViewModel.Tags.ToLower(), topic); } // Subscribe the user to the topic as they have checked the checkbox if (topicViewModel.SubscribeToTopic) { // Create the notification var topicNotification = new TopicNotification { Topic = topic, User = LoggedOnUser }; //save _topicNotificationService.Add(topicNotification); } try { unitOfWork.Commit(); if (!moderate) { successfullyCreated = true; } } catch (Exception ex) { unitOfWork.Rollback(); LoggingService.Error(ex); ModelState.AddModelError(string.Empty, LocalizationService.GetResourceString("Errors.GenericMessage")); } } else { unitOfWork.Rollback(); ModelState.AddModelError(string.Empty, LocalizationService.GetResourceString("Errors.PossibleSpam")); } } else { ModelState.AddModelError(string.Empty, LocalizationService.GetResourceString("Errors.GenericMessage")); } } } using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork()) { if (successfullyCreated) { // Success so now send the emails NotifyNewTopics(category, unitOfWork); // Redirect to the newly created topic return Redirect(string.Format("{0}?postbadges=true", topic.NiceUrl)); } if (moderate) { // Moderation needed // Tell the user the topic is awaiting moderation TempData[AppConstants.MessageViewBagName] = new GenericMessageViewModel { Message = LocalizationService.GetResourceString("Moderate.AwaitingModeration"), MessageType = GenericMessages.info }; return RedirectToAction("Index", "Home"); } } } return View(topicViewModel); }