public async Task<ActionResult> SubverseStylesheetEditor(Subverse updatedModel)
        {
            try
            {
                if (!ModelState.IsValid) return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
                var existingSubverse = _db.Subverses.Find(updatedModel.name);

                // check if subverse exists before attempting to edit it
                if (existingSubverse != null)
                {
                    // check if user requesting edit is authorized to do so for current subverse
                    // check that the user requesting to edit subverse settings is subverse owner!
                    var subAdmin = _db.SubverseAdmins.FirstOrDefault(x => x.SubverseName == updatedModel.name && x.Username == User.Identity.Name && x.Power <= 2);
                    
                    // user was not authorized to commit the changes, drop attempt
                    if (subAdmin == null) return new EmptyResult();

                    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");
                        }
                    }
                    else
                    {
                        existingSubverse.stylesheet = updatedModel.stylesheet;
                    }

                    await _db.SaveChangesAsync();
                    DataCache.Subverse.Remove(existingSubverse.name);

                    // go back to this subverse
                    return RedirectToAction("SubverseIndex", "Subverses", new { subversetoshow = updatedModel.name });
                }

                ModelState.AddModelError(string.Empty, "Sorry, The subverse you are trying to edit does not exist.");
                return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
            }
            catch (Exception)
            {
                ModelState.AddModelError(string.Empty, "Something bad happened.");
                return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
            }
        }
        public async Task<ActionResult> SubverseSettings(Subverse updatedModel)
        {
            try
            {
                if (!ModelState.IsValid) return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
                var existingSubverse = _db.Subverses.Find(updatedModel.name);

                // check if subverse exists before attempting to edit it
                if (existingSubverse != null)
                {
                    // check if user requesting edit is authorized to do so for current subverse
                    if (!UserHelper.IsUserSubverseModerator(User.Identity.Name, updatedModel.name))
                    {
                        return new EmptyResult();
                    }

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

                    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");
                        }
                    }
                    else
                    {
                        existingSubverse.stylesheet = updatedModel.stylesheet;
                    }

                    existingSubverse.rated_adult = updatedModel.rated_adult;
                    existingSubverse.private_subverse = updatedModel.private_subverse;
                    existingSubverse.enable_thumbnails = updatedModel.enable_thumbnails;
                    existingSubverse.authorized_submitters_only = updatedModel.authorized_submitters_only;
                    existingSubverse.exclude_sitewide_bans = updatedModel.exclude_sitewide_bans;
                    existingSubverse.minimumdownvoteccp = updatedModel.minimumdownvoteccp;

                    // these properties are currently not implemented but they can be saved and edited for future use
                    existingSubverse.type = updatedModel.type;
                    existingSubverse.label_submit_new_link = updatedModel.label_submit_new_link;
                    existingSubverse.label_sumit_new_selfpost = updatedModel.label_sumit_new_selfpost;
                    existingSubverse.submission_text = updatedModel.submission_text;
                    existingSubverse.allow_default = updatedModel.allow_default;

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

                    // only subverse owners should be able to convert a sub to anonymized mode
                    if (UserHelper.IsUserSubverseAdmin(User.Identity.Name, updatedModel.name))
                    {
                        existingSubverse.anonymized_mode = updatedModel.anonymized_mode;
                    }

                    await _db.SaveChangesAsync();
                    DataCache.Subverse.Remove(existingSubverse.name);

                    // go back to this subverse
                    return RedirectToAction("SubverseIndex", "Subverses", new { subversetoshow = 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");
            }
            catch (Exception)
            {
                ModelState.AddModelError(string.Empty, "Something bad happened.");
                return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
            }
        }
        public async Task<ActionResult> CreateSubverse([Bind(Include = "Name, Title, Description, Type, Sidebar, Creation_date, Owner")] AddSubverse subverseTmpModel)
        {
            // abort if model state is invalid
            if (!ModelState.IsValid) return View();

            int minimumCcp = Settings.MinimumCcp;
            int maximumOwnedSubs = Settings.MaximumOwnedSubs;

            // verify recaptcha if user has less than minimum required CCP
            if (Karma.CommentKarma(User.Identity.Name) < minimumCcp)
            {
                // begin recaptcha check
                bool isCaptchaCodeValid = await ReCaptchaUtility.Validate(Request);

                if (!isCaptchaCodeValid)
                {
                    ModelState.AddModelError("", "Incorrect recaptcha answer.");

                    // TODO 
                    // SET PREVENT SPAM DELAY TO 0

                    return View();
                }
            }

            // only allow users with less than maximum allowed subverses to create a subverse
            var amountOfOwnedSubverses = _db.SubverseAdmins
                .Where(s => s.Username == User.Identity.Name && s.Power == 1)
                .ToList();
            if (amountOfOwnedSubverses.Count >= maximumOwnedSubs)
            {
                ModelState.AddModelError(string.Empty, "Sorry, you can not own more than " + maximumOwnedSubs + " subverses.");
                return View();
            }

            // check if subverse already exists
            if (DataCache.Subverse.Retrieve(subverseTmpModel.Name) != null)
            {
                ModelState.AddModelError(string.Empty, "Sorry, The subverse you are trying to create already exists, but you can try to claim it by submitting a takeover request to /v/subverserequest.");
                return View();
            }

            try
            {
                // setup default values and create the subverse
                var subverse = new Subverse
                {
                    name = subverseTmpModel.Name,
                    title = "/v/" + subverseTmpModel.Name,
                    description = subverseTmpModel.Description,
                    sidebar = subverseTmpModel.Sidebar,
                    creation_date = DateTime.Now,
                    type = "link",
                    enable_thumbnails = true,
                    rated_adult = false,
                    private_subverse = false,
                    minimumdownvoteccp = 0,
                    admin_disabled = false
                };

                _db.Subverses.Add(subverse);
                await _db.SaveChangesAsync();

                // subscribe user to the newly created subverse
                Voat.Utilities.UserHelper.SubscribeToSubverse(subverseTmpModel.Owner, subverse.name);

                // register user as the owner of the newly created subverse
                var tmpSubverseAdmin = new SubverseAdmin
                {
                    SubverseName = subverseTmpModel.Name,
                    Username = User.Identity.Name,
                    Power = 1
                };
                _db.SubverseAdmins.Add(tmpSubverseAdmin);
                await _db.SaveChangesAsync();

                // go to newly created Subverse
                return RedirectToAction("SubverseIndex", "Subverses", new { subversetoshow = subverseTmpModel.Name });
            }
            catch (Exception)
            {
                ModelState.AddModelError(string.Empty, "Something bad happened, please report this to /v/voatdev. Thank you.");
                return View();
            }
        }
Exemple #4
0
        // various spam checks, to be replaced with new rule engine
        public static async Task<string> PreAddSubmissionCheck(Message submissionModel, HttpRequestBase request, string userName, Subverse targetSubverse, Func<HttpRequestBase, Task<bool>> captchaValidator)
        {
            // TODO: reject if a submission with this title was posted in the last 60 minutes

            // check posting quotas if user is posting to subs they do not moderate
            if (!UserHelper.IsUserSubverseModerator(userName, submissionModel.Subverse))
            {
                // reject if user has reached global daily submission quota
                if (UserHelper.UserDailyGlobalPostingQuotaUsed(userName))
                {
                    return ("You have reached your daily global submission quota.");
                }

                // reject if user has reached global hourly submission quota
                if (UserHelper.UserHourlyGlobalPostingQuotaUsed(userName))
                {
                    return ("You have reached your hourly global submission quota.");
                }

                // check if user has reached hourly posting quota for target subverse
                if (UserHelper.UserHourlyPostingQuotaForSubUsed(userName, submissionModel.Subverse))
                {
                    return ("You have reached your hourly submission quota for this subverse.");
                }

                // check if user has reached daily posting quota for target subverse
                if (UserHelper.UserDailyPostingQuotaForSubUsed(userName, submissionModel.Subverse))
                {
                    return ("You have reached your daily submission quota for this subverse.");
                }
            }

            // verify recaptcha if user has less than 25 CCP
            var userCcp = Karma.CommentKarma(userName);
            if (userCcp < 25)
            {
                bool isCaptchaCodeValid = await captchaValidator(request);

                if (!isCaptchaCodeValid)
                {
                    // TODO: SET PREVENT SPAM DELAY TO 0
                    return ("Incorrect recaptcha answer.");
                }
            }

            // if user CCP or SCP is less than -50, allow only X submissions per 24 hours
            var userScp = Karma.LinkKarma(userName);
            if (userCcp <= -50 || userScp <= -50)
            {
                var quotaUsed = UserHelper.UserDailyPostingQuotaForNegativeScoreUsed(userName);
                if (quotaUsed)
                {
                    return ("You have reached your daily submission quota. Your current quota is " + Settings.DailyPostingQuotaForNegativeScore + " submission(s) per 24 hours.");
                }
            }

            // check if subverse has "authorized_submitters_only" set and dissalow submission if user is not allowed submitter
            if (targetSubverse.authorized_submitters_only)
            {
                if (!UserHelper.IsUserSubverseModerator(userName, targetSubverse.name))
                {
                    return ("You are not authorized to submit links or start discussions in this subverse. Please contact subverse moderators for authorization.");
                }
            }

            // null is returned if all checks have passed
            return null;
        }
Exemple #5
0
        // add new link submission
        public static async Task<string> AddNewSubmission(Message submissionModel, Subverse targetSubverse, string userName)
        {
            using (var db = new voatEntities())
            {
                // LINK TYPE SUBMISSION
                if (submissionModel.Type == 2)
                {
                    // strip unicode if title contains unicode
                    if (ContainsUnicode(submissionModel.Linkdescription))
                    {
                        submissionModel.Linkdescription = StripUnicode(submissionModel.Linkdescription);
                    }

                    // reject if title is whitespace or < than 5 characters
                    if (submissionModel.Linkdescription.Length < 5 || String.IsNullOrWhiteSpace(submissionModel.Linkdescription))
                    {
                        return ("The title may not be less than 5 characters.");
                    }

                    // make sure the input URI is valid
                    if (!UrlUtility.IsUriValid(submissionModel.MessageContent))
                    {
                        // ABORT
                        return ("The URI you are trying to submit is invalid.");
                    }

                    // check if target subvere allows submissions from globally banned hostnames
                    if (!targetSubverse.exclude_sitewide_bans)
                    {
                        // check if hostname is banned before accepting submission
                        var domain = UrlUtility.GetDomainFromUri(submissionModel.MessageContent);
                        if (BanningUtility.IsHostnameBanned(domain))
                        {
                            // ABORT
                            return ("The hostname you are trying to submit is banned.");
                        }
                    }

                    // check if user has reached daily crossposting quota
                    if (UserHelper.DailyCrossPostingQuotaUsed(userName, submissionModel.MessageContent))
                    {
                        // ABORT
                        return ("You have reached your daily crossposting quota for this URL.");
                    }

                    // check if target subverse has thumbnails setting enabled before generating a thumbnail
                    if (targetSubverse.enable_thumbnails)
                    {
                        // try to generate and assign a thumbnail to submission model
                        submissionModel.Thumbnail = await ThumbGenerator.ThumbnailFromSubmissionModel(submissionModel);
                    }

                    // flag the submission as anonymized if it was submitted to a subverse with active anonymized_mode
                    if (targetSubverse.anonymized_mode)
                    {
                        submissionModel.Anonymized = true;
                    }
                    else
                    {
                        submissionModel.Name = userName;
                    }

                    // accept submission and save it to the database
                    submissionModel.Subverse = targetSubverse.name;
                    submissionModel.Likes = 1;
                    db.Messages.Add(submissionModel);

                    // update last submission received date for target subverse
                    targetSubverse.last_submission_received = DateTime.Now;
                    await db.SaveChangesAsync();
                }
                else
                // MESSAGE TYPE SUBMISSION
                {
                    // strip unicode if submission contains unicode
                    if (ContainsUnicode(submissionModel.Title))
                    {
                        submissionModel.Title = StripUnicode(submissionModel.Title);
                    }

                    // reject if title is whitespace or less than 5 characters
                    if (submissionModel.Title.Length < 5 || String.IsNullOrWhiteSpace(submissionModel.Title))
                    {
                        return ("Sorry, submission title may not be less than 5 characters.");
                    }

                    // flag the submission as anonymized if it was submitted to a subverse with active anonymized_mode
                    if (targetSubverse.anonymized_mode)
                    {
                        submissionModel.Anonymized = true;
                    }
                    else
                    {
                        submissionModel.Name = userName;
                    }

                    // grab server timestamp and modify submission timestamp to have posting time instead of "started writing submission" time
                    submissionModel.Subverse = targetSubverse.name;
                    submissionModel.Date = DateTime.Now;
                    submissionModel.Likes = 1;
                    db.Messages.Add(submissionModel);

                    // update last submission received date for target subverse
                    targetSubverse.last_submission_received = DateTime.Now;

                    if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPreSave))
                    {
                        submissionModel.MessageContent = ContentProcessor.Instance.Process(submissionModel.MessageContent, ProcessingStage.InboundPreSave, submissionModel);
                    }

                    await db.SaveChangesAsync();

                    if (ContentProcessor.Instance.HasStage(ProcessingStage.InboundPostSave))
                    {
                        ContentProcessor.Instance.Process(submissionModel.MessageContent, ProcessingStage.InboundPostSave, submissionModel);
                    }
                }
            }
            
            // null is returned if no errors were raised
            return null;
        }
        public async Task<ActionResult> SubverseSettings(Subverse updatedModel)
        {
            try
            {
                if (!ModelState.IsValid) return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
                var existingSubverse = _db.Subverses.Find(updatedModel.Name);

                // check if subverse exists before attempting to edit it
                if (existingSubverse != null)
                {
                    // check if user requesting edit is authorized to do so for current subverse
                    if (!UserHelper.IsUserSubverseModerator(User.Identity.Name, updatedModel.Name))
                    {
                        return new EmptyResult();
                    }

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

                    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");
                        }
                    }
                    else
                    {
                        existingSubverse.Stylesheet = updatedModel.Stylesheet;
                    }

                    existingSubverse.IsAdult = updatedModel.IsAdult;
                    existingSubverse.IsPrivate = updatedModel.IsPrivate;
                    existingSubverse.IsThumbnailEnabled = updatedModel.IsThumbnailEnabled;
                    existingSubverse.IsAuthorizedOnly = updatedModel.IsAuthorizedOnly;
                    existingSubverse.ExcludeSitewideBans = updatedModel.ExcludeSitewideBans;
                    existingSubverse.MinCCPForDownvote = updatedModel.MinCCPForDownvote;

                    // 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 && updatedModel.IsAnonymized == false)
                    {
                        ModelState.AddModelError(string.Empty, "Sorry, this subverse is permanently locked to anonymized mode.");
                        return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
                    }

                    // only subverse owners should be able to convert a sub to anonymized mode
                    if (UserHelper.IsUserSubverseAdmin(User.Identity.Name, updatedModel.Name))
                    {
                        existingSubverse.IsAnonymized = updatedModel.IsAnonymized;
                    }

                    await _db.SaveChangesAsync();
                    DataCache.Subverse.Remove(existingSubverse.Name);

                    // go back to this subverse
                    return RedirectToAction("SubverseIndex", "Subverses", new { subversetoshow = 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");
            }
            catch (Exception)
            {
                ModelState.AddModelError(string.Empty, "Something bad happened.");
                return View("~/Views/Subverses/Admin/SubverseSettings.cshtml");
            }
        }