protected override RuleOutcome EvaluateRule(VoatRuleContext context)
        {
            string content = context.PropertyBag.CommentContent;

            //Check banned domains in submission content
            var containsBannedDomain = BanningUtility.ContentContainsBannedDomain(context.Subverse.Name, content);

            if (containsBannedDomain)
            {
                return(CreateOutcome(RuleResult.Denied, "Comment contains banned domains"));
            }

            return(Allowed);
        }
예제 #2
0
        public async Task <ActionResult> EditComment([Bind(Include = "ID, Content")] Comment commentModel)
        {
            if (ModelState.IsValid)
            {
                var existingComment = _db.Comments.Find(commentModel.ID);

                if (existingComment != null)
                {
                    if (existingComment.UserName.Trim() == User.Identity.Name && !existingComment.IsDeleted)
                    {
                        bool containsBannedDomain = BanningUtility.ContentContainsBannedDomain(existingComment.Submission.Subverse, commentModel.Content);
                        if (containsBannedDomain)
                        {
                            return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Comment contains links to banned domain(s)."));
                        }

                        existingComment.LastEditDate = DateTime.Now;
                        existingComment.Content      = commentModel.Content;

                        if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPreSave))
                        {
                            existingComment.Content = ContentProcessor.Instance.Process(existingComment.Content, ProcessingStage.InboundPreSave, existingComment);
                        }

                        //save fully formatted content
                        var formattedComment = Formatting.FormatMessage(existingComment.Content);
                        existingComment.FormattedContent = formattedComment;

                        await _db.SaveChangesAsync();

                        if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPostSave))
                        {
                            ContentProcessor.Instance.Process(existingComment.Content, ProcessingStage.InboundPostSave, existingComment);
                        }

                        //return the formatted comment so that it can replace the existing html comment which just got modified
                        return(Json(new { response = formattedComment }));
                    }
                    return(Json("Unauthorized edit.", JsonRequestBehavior.AllowGet));
                }
            }

            if (Request.IsAjaxRequest())
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            return(Json("Unauthorized edit or comment not found - comment ID was.", JsonRequestBehavior.AllowGet));
        }
예제 #3
0
        protected override RuleOutcome EvaluateRule(VoatRuleContext context)
        {
            ChatMessage message     = context.PropertyBag.ChatMessage;
            var         currentDate = Data.Repository.CurrentDate;

            if (message == null)
            {
                return(CreateOutcome(RuleResult.Denied, "Rule needs chat message contexarstt"));
            }

            if (BanningUtility.ContentContainsBannedDomain(null, message.Message))
            {
                return(CreateOutcome(RuleResult.Denied, "Content contains banned domain"));
            }

            var history      = ChatHistory.History(message.RoomID);
            var historyArray = history.ToArray();

            //Copy Pasta
            //check full history
            var duplicateFound = false;
            //duplicateFound = historyArray.Any(x => x.UserName == message.UserName && x.Message.IsEqual(message.Message.TrimSafe()));

            var lastMessage = historyArray.LastOrDefault(x => x.User.UserName == message.User.UserName);

            if (lastMessage != null)
            {
                duplicateFound = lastMessage.Message.IsEqual(message.Message.TrimSafe());
            }

            if (duplicateFound)
            {
                return(CreateOutcome(RuleResult.Denied, "Chat message considered copy/paste spam"));
            }

            ////Spammer
            var countInWindow = historyArray.Count(x => x.User.UserName == message.User.UserName && currentDate.Subtract(x.CreationDate) <= _timeSpanWindow);

            if (countInWindow >= _count)
            {
                return(CreateOutcome(RuleResult.Denied, "Chat message considered spamming by user"));
            }

            return(base.EvaluateRule(context));
        }
예제 #4
0
        protected override RuleOutcome EvaluateRule(VoatRuleContext context)
        {
            UserSubmission submission = context.PropertyBag.UserSubmission;

            //Check banned domains in submission content
            var containsBannedDomain = false;

            switch (submission.Type)
            {
            case SubmissionType.Link:
                containsBannedDomain = BanningUtility.ContentContainsBannedDomain(context.Subverse.Name, $"{submission.Title} {submission.Url}");
                break;

            case SubmissionType.Text:
                containsBannedDomain = BanningUtility.ContentContainsBannedDomain(context.Subverse.Name, $"{submission.Title} {submission.Content}");
                break;
            }
            if (containsBannedDomain)
            {
                return(CreateOutcome(RuleResult.Denied, "Submission contains banned domains"));
            }

            return(Allowed);
        }
        public async Task <ActionResult> Update(SubverseSettingsViewModel updatedModel)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    SetNavigationViewModel(updatedModel.Name);
                    return(View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel));
                }
                var existingSubverse = _db.Subverse.FirstOrDefault(x => x.Name.ToUpper() == updatedModel.Name.ToUpper());

                // check if subverse exists before attempting to edit it
                if (existingSubverse != null)
                {
                    SetNavigationViewModel(existingSubverse.Name);

                    // check if user requesting edit is authorized to do so for current subverse
                    if (!ModeratorPermission.HasPermission(User, updatedModel.Name, Domain.Models.ModeratorAction.ModifySettings))
                    {
                        return(new EmptyResult());
                    }
                    //check description for banned domains
                    if (BanningUtility.ContentContainsBannedDomain(existingSubverse.Name, updatedModel.Description))
                    {
                        ModelState.AddModelError(string.Empty, "Sorry, description text contains banned domains.");
                        return(View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel));
                    }
                    //check sidebar for banned domains
                    if (BanningUtility.ContentContainsBannedDomain(existingSubverse.Name, updatedModel.SideBar))
                    {
                        ModelState.AddModelError(string.Empty, "Sorry, sidebar text contains banned domains.");
                        return(View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel));
                    }

                    // TODO investigate if EntityState is applicable here and use that instead
                    // db.Entry(updatedModel).State = EntityState.Modified;

                    existingSubverse.Title       = updatedModel.Title;
                    existingSubverse.Description = updatedModel.Description;
                    existingSubverse.SideBar     = updatedModel.SideBar;

                    //if (updatedModel.Stylesheet != null)
                    //{
                    //    if (updatedModel.Stylesheet.Length < 50001)
                    //    {
                    //        existingSubverse.Stylesheet = updatedModel.Stylesheet;
                    //    }
                    //    else
                    //    {
                    //        ModelState.AddModelError(string.Empty, "Sorry, custom CSS limit is set to 50000 characters.");
                    //        return View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel);
                    //    }
                    //}
                    //else
                    //{
                    //    existingSubverse.Stylesheet = updatedModel.Stylesheet;
                    //}

                    existingSubverse.IsAdult = updatedModel.IsAdult;

                    existingSubverse.IsThumbnailEnabled  = updatedModel.IsThumbnailEnabled;
                    existingSubverse.IsAuthorizedOnly    = updatedModel.IsAuthorizedOnly;
                    existingSubverse.ExcludeSitewideBans = updatedModel.ExcludeSitewideBans;

                    //Only update if time lock has expired
                    if (existingSubverse.LastUpdateDate == null || (Repository.CurrentDate.Subtract(existingSubverse.LastUpdateDate.Value) > TimeSpan.FromHours(VoatSettings.Instance.SubverseUpdateTimeLockInHours)))
                    {
                        existingSubverse.MinCCPForDownvote = updatedModel.MinCCPForDownvote;
                        existingSubverse.IsPrivate         = updatedModel.IsPrivate;
                    }

                    // these properties are currently not implemented but they can be saved and edited for future use
                    //existingSubverse.Type = updatedModel.Type;
                    //existingSubverse.SubmitLinkLabel = updatedModel.SubmitLinkLabel;
                    //existingSubverse.SubmitPostLabel = updatedModel.SubmitPostLabel;
                    //existingSubverse.SubmissionText = updatedModel.SubmissionText;
                    //existingSubverse.IsDefaultAllowed = updatedModel.IsDefaultAllowed;

                    //if (existingSubverse.IsAnonymized == true && updatedModel.IsAnonymized == false)
                    //{
                    //    ModelState.AddModelError(string.Empty, "Sorry, this subverse is permanently locked to anonymized mode.");
                    //    return View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel);
                    //}

                    // only subverse owners should be able to convert a sub to anonymized mode
                    if (ModeratorPermission.IsLevel(User, updatedModel.Name, Domain.Models.ModeratorLevel.Owner))
                    {
                        existingSubverse.IsAnonymized = updatedModel.IsAnonymized;
                    }

                    existingSubverse.LastUpdateDate = Repository.CurrentDate;
                    await _db.SaveChangesAsync();

                    //purge new minified CSS
                    CacheHandler.Instance.Remove(CachingKey.SubverseStylesheet(existingSubverse.Name));

                    //purge subvere
                    CacheHandler.Instance.Remove(CachingKey.Subverse(existingSubverse.Name));

                    // go back to this subverse
                    return(RedirectToRoute(Models.ROUTE_NAMES.SUBVERSE_INDEX, new { subverse = updatedModel.Name }));

                    // user was not authorized to commit the changes, drop attempt
                }
                ModelState.AddModelError(string.Empty, "Sorry, The subverse you are trying to edit does not exist.");
                return(View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel));
            }
            catch (Exception ex)
            {
                EventLogger.Instance.Log(ex);
                ModelState.AddModelError(string.Empty, "Something bad happened.");
                return(View("~/Views/Subverses/Admin/SubverseSettings.cshtml", updatedModel));
            }
        }
예제 #6
0
        public async Task <ActionResult> SubmitComment([Bind(Include = "ID, Content, SubmissionID, ParentID")] Comment commentModel)
        {
            commentModel.CreationDate = DateTime.Now;
            commentModel.UserName     = User.Identity.Name;
            commentModel.Votes        = 0;
            commentModel.UpCount      = 0;

            if (ModelState.IsValid)
            {
                // flag the comment as anonymized if it was submitted to a sub which has active anonymized_mode
                var submission = DataCache.Submission.Retrieve(commentModel.SubmissionID.Value);
                var subverse   = DataCache.Subverse.Retrieve(submission.Subverse);
                commentModel.IsAnonymized = submission.IsAnonymized || subverse.IsAnonymized;

                // if user CCP is < 50, allow only X comment submissions per 24 hours
                var userCcp = Karma.CommentKarma(User.Identity.Name);
                if (userCcp <= -50)
                {
                    var quotaUsed = UserHelper.UserDailyCommentPostingQuotaForNegativeScoreUsed(User.Identity.Name);
                    if (quotaUsed)
                    {
                        return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "You have reached your daily comment quota. Your current quota is " + Settings.DailyCommentPostingQuotaForNegativeScore.ToString() + " comment(s) per 24 hours."));
                        //ModelState.AddModelError("", "You have reached your daily comment quota. Your current quota is " + Settings.DailyCommentPostingQuotaForNegativeScore + " comment(s) per 24 hours.");
                        //return View();
                    }
                }

                // check if author is banned, don't save the comment or send notifications if true
                if (!UserHelper.IsUserGloballyBanned(User.Identity.Name) && !UserHelper.IsUserBannedFromSubverse(User.Identity.Name, submission.Subverse))
                {
                    bool containsBannedDomain = BanningUtility.ContentContainsBannedDomain(subverse.Name, commentModel.Content);
                    if (containsBannedDomain)
                    {
                        return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Comment contains links to banned domain(s)."));
                    }


                    if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPreSave))
                    {
                        commentModel.Content = ContentProcessor.Instance.Process(commentModel.Content, ProcessingStage.InboundPreSave, commentModel);
                    }

                    //save fully formatted content
                    var formattedComment = Formatting.FormatMessage(commentModel.Content);
                    commentModel.FormattedContent = formattedComment;

                    _db.Comments.Add(commentModel);

                    await _db.SaveChangesAsync();

                    DataCache.CommentTree.AddCommentToTree(commentModel);

                    if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPostSave))
                    {
                        ContentProcessor.Instance.Process(commentModel.Content, ProcessingStage.InboundPostSave, commentModel);
                    }

                    // send comment reply notification to parent comment author if the comment is not a new root comment
                    await NotificationManager.SendCommentNotification(commentModel,
                                                                      new Action <string>(recipient => {
                        //get count of unread notifications
                        int unreadNotifications = UserHelper.UnreadTotalNotificationsCount(recipient);
                        // send SignalR realtime notification to recipient
                        var hubContext = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext <MessagingHub>();
                        hubContext.Clients.User(recipient).setNotificationsPending(unreadNotifications);
                    })
                                                                      );
                }
                if (Request.IsAjaxRequest())
                {
                    var comment = commentModel;

                    ViewBag.CommentId   = comment.ID;               //why?
                    ViewBag.rootComment = comment.ParentID == null; //why?

                    if (submission.IsAnonymized || subverse.IsAnonymized)
                    {
                        comment.UserName = comment.ID.ToString(CultureInfo.InvariantCulture);
                    }

                    var model = new CommentBucketViewModel(comment);

                    return(PartialView("~/Views/Shared/Submissions/_SubmissionComment.cshtml", model));
                    //return new HttpStatusCodeResult(HttpStatusCode.OK);
                }
                if (Request.UrlReferrer != null)
                {
                    var url = Request.UrlReferrer.AbsolutePath;
                    return(Redirect(url));
                }
            }
            if (Request.IsAjaxRequest())
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            ModelState.AddModelError(String.Empty, "Sorry, you are either banned from this sub or doing that too fast. Please try again in 2 minutes.");
            return(View("~/Views/Help/SpeedyGonzales.cshtml"));
        }
예제 #7
0
        public async Task <ActionResult> Submit([Bind(Include = "ID,Votes,Name,CreationDate,Type,LinkDescription,Title,Rank,Content,Subverse")] Submission submission)
        {
            // abort if model state is invalid
            if (!ModelState.IsValid)
            {
                return(View());
            }

            // save temp values for the view in case submission fails
            ViewBag.selectedSubverse = submission.Subverse;
            ViewBag.message          = submission.Content;
            ViewBag.title            = submission.Title;
            ViewBag.linkDescription  = submission.LinkDescription;

            // grab server timestamp and modify submission timestamp to have posting time instead of "started writing submission" time
            submission.CreationDate = DateTime.Now;

            // check if user is banned
            if (UserHelper.IsUserGloballyBanned(User.Identity.Name) || UserHelper.IsUserBannedFromSubverse(User.Identity.Name, submission.Subverse))
            {
                ViewBag.SelectedSubverse = submission.Subverse;
                return(View("~/Views/Home/Comments.cshtml", submission));
            }
            if (String.IsNullOrEmpty(submission.Subverse))
            {
                ModelState.AddModelError(string.Empty, "Please enter a subverse.");
                return(View("Submit"));
            }
            // check if subverse exists
            var targetSubverse = _db.Subverses.Find(submission.Subverse.Trim());

            if (targetSubverse == null || submission.Subverse.Equals("all", StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError(string.Empty, "Sorry, The subverse you are trying to post to does not exist.");
                return(View("Submit"));
            }

            //wrap captcha check in anon method as following method is in non UI dll
            var captchaCheck = new Func <HttpRequestBase, Task <bool> >(request => {
                return(ReCaptchaUtility.Validate(request));
            });

            // check if this submission is valid and good to go
            var preProcessCheckResult = await Submissions.PreAddSubmissionCheck(submission, Request, User.Identity.Name, targetSubverse, captchaCheck);

            if (preProcessCheckResult != null)
            {
                ModelState.AddModelError(string.Empty, preProcessCheckResult);
                return(View("Submit"));
            }

            // submission is a link post
            if (submission.Type == 2 && submission.Content != null && submission.LinkDescription != null)
            {
                // check if same link was submitted before and deny submission
                var existingSubmission = _db.Submissions.FirstOrDefault(s => s.Content.Equals(submission.Content, StringComparison.OrdinalIgnoreCase) && s.Subverse.Equals(submission.Subverse, StringComparison.OrdinalIgnoreCase));

                // submission is a repost, discard it and inform the user
                if (existingSubmission != null)
                {
                    ModelState.AddModelError(string.Empty, "Sorry, this link has already been submitted by someone else.");

                    // todo: offer the option to repost after informing the user about it
                    return(RedirectToRoute(
                               "SubverseComments",
                               new
                    {
                        controller = "Comment",
                        action = "Comments",
                        id = existingSubmission.ID,
                        subversetoshow = existingSubmission.Subverse
                    }
                               ));
                }

                // process new link submission
                var addLinkSubmissionResult = await Submissions.AddNewSubmission(submission, targetSubverse, User.Identity.Name);

                if (addLinkSubmissionResult != null)
                {
                    ModelState.AddModelError(string.Empty, addLinkSubmissionResult);
                    return(View("Submit"));
                }
                // update last submission received date for target subverse
                targetSubverse.LastSubmissionDate = DateTime.Now;
                await _db.SaveChangesAsync();
            }
            // submission is a message type submission
            else if (submission.Type == 1 && submission.Title != null)
            {
                var containsBannedDomain = BanningUtility.ContentContainsBannedDomain(targetSubverse.Name, submission.Content);
                if (containsBannedDomain)
                {
                    ModelState.AddModelError(string.Empty, "Sorry, this post contains links to banned domains.");
                    return(View("Submit"));
                }

                // process new message type submission
                var addMessageSubmissionResult = await Submissions.AddNewSubmission(submission, targetSubverse, User.Identity.Name);

                if (addMessageSubmissionResult != null)
                {
                    ModelState.AddModelError(string.Empty, addMessageSubmissionResult);
                    return(View("Submit"));
                }
                // update last submission received date for target subverse
                targetSubverse.LastSubmissionDate = DateTime.Now;
                await _db.SaveChangesAsync();
            }

            // redirect to comments section of newly posted submission
            return(RedirectToRoute(
                       "SubverseComments",
                       new
            {
                controller = "Comment",
                action = "Comments",
                id = submission.ID,
                subversetoshow = submission.Subverse
            }
                       ));
        }