public virtual ActionResult ArticleDetails(long articleId) { ActionResult returnValue = null; if (!ProviderArticle.Exists(articleId)) { returnValue = RedirectToAction(MVC.Error.Index(404)); } else { ProviderArticle anArticle = new ProviderArticle(articleId); if (anArticle.IsPublished || ProviderCurrentMember.Instance.CanEdit(anArticle)) { // increment view count and don't update edit date when saving article anArticle.ViewCount += 1; anArticle.Save(); // Send a shadow vote ProviderArticleVote shadowVote = new ProviderArticleVote(); shadowVote.IsShadowVote = true; shadowVote.ArticleId = anArticle.Id.Value; shadowVote.Save(); returnValue = View(new DetailsVM(anArticle, ProviderCurrentMember.Instance)); } else { returnValue = RedirectToAction(MVC.Error.Index(404)); } } return returnValue; }
public bool Save(ProviderCurrentMember currentMember) { if (!currentMember.IsNew) { ProviderArticle anArticle; List<long> tempList = new List<long>(ArticleIdList); foreach (long id in tempList) { anArticle = new ProviderArticle(id); // if the article already has a value then don't override or add a new one. if (!anArticle.MemberId.HasValue) { anArticle.MemberId = currentMember.Id; anArticle.Save(); } ArticleIdList.Remove(id); } } return true; }
public static bool AssociatePhotos(string articleText, ProviderArticle anArticle, ref List<string> errorList) { bool returnValue = true; //Detach all Photos from their relationship with the article. anArticle.RemoveAllPhotos(); // Note: There is a bit of a performance hit since we load the article body into the HtmlParser and then later do it again in ProviderArticle Save function. // We should revisit this area when we need to do performance optimization. List<string> imageHosts = InsideWordWebSettings.ImageHosts; List<ImageInfo> imageList = HtmlParser.GetImageInfos(articleText, null); int orderedCount = 1; Uri srcUri = null; foreach (ImageInfo anImageInfo in imageList) { ProviderPhotoRecord aRecord = new ProviderPhotoRecord(); if(!Uri.TryCreate(anImageInfo.Src, UriKind.Absolute, out srcUri)) { errorList.Add(IWStringUtility.SuffixedNumber(orderedCount) + " photo has a bad link. Delete it and recreate it."); returnValue = false; } else { if (!aRecord.Load(srcUri)) { aRecord = new ProviderPhotoRecord(anImageInfo); aRecord.Save(); List<ProviderPhotoRecord> fakeThumbnailList = ProviderPhotoRecord.CreateFakeThumbnails(aRecord); foreach (ProviderPhotoRecord fakeThumbnail in fakeThumbnailList) { fakeThumbnail.Save(); } } anArticle.AddPhoto(aRecord.Id.Value); } orderedCount++; } return returnValue; }
public static void AddComment(string textComment, ProviderCurrentMember currentMember, ProviderArticle anArticle , ref ProviderConversation conversation, ref ProviderComment comment) { if (!currentMember.CanEdit(comment)) { throw new Exception(ErrorStrings.OPERATION_NO_RIGHTS); } try { if (conversation.IsNew) { conversation.MemberId = currentMember.Id; conversation.ArticleId = anArticle.Id; conversation.CreateDate = DateTime.UtcNow; } conversation.EditDate = DateTime.UtcNow; conversation.Save(); //make sure the comment code is after the save since this //conversation doesn't exist yet. comment.ConversationId = conversation.Id.Value; comment.MemberId = currentMember.Id; comment.Text = textComment; comment.EditDate = DateTime.UtcNow; comment.CreateDate = DateTime.UtcNow; comment.IsHidden = false; comment.Save(); } catch (Exception caughtException) { // DO NOT LOG THIS. It is the responsibility of the calling program to handle the exception throw new Exception("Failed to save comment", caughtException); } }
/// <summary> /// Function to send an notification that the article was commented on /// </summary> /// <param name="anArticle">Article that was commented on</param> /// <param name="aMember">Member that will receive the e-mail</param> /// <returns>true if the e-mail was sent successfully and false otherwise.</returns> public bool SendVoteNotificationEmail(MailAddress email, ProviderArticle anArticle) { string articleUrl = HttpHost + "article/" + anArticle.Id; string voteResult = "."; if (anArticle.CountVotes > 0) { voteResult = " to a total of " + anArticle.CountVotes+"."; } string emailBody = "DO NOT REPLY TO THIS E-MAIL<br />" + "<br />" + "<br />" + "Your article, <a href='" + articleUrl + "'>" + anArticle.Title + "</a>, has been voted up"+voteResult + "<br />" + "<br />" + "<br />"; //+ DidYouKnow(); MailMessage aMailMessage = new MailMessage("*****@*****.**", email.Address, "InsideWord - Your article has been voted up! " + anArticle.Title, emailBody); aMailMessage.IsBodyHtml = true; DefaultSmtp.Send(aMailMessage); return true; }
/// <summary> /// Function to send an Edit/Delete e-mail to a member. /// </summary> /// <param name="anArticle">Article that member would like to edit/delete</param> /// <param name="aMember">Member that will receive the e-mail</param> /// <returns>true if the e-mail was sent successfully and false otherwise.</returns> public bool SendEditArticleEmail(MailAddress email, ProviderArticle anArticle, ProviderMember aMember) { ProviderIssuedKey nonceIssuedKey = new ProviderIssuedKey(); nonceIssuedKey.LoadOrCreate(aMember.Id.Value, email.Address, true, null, true); // create a month issued key for editing the article ProviderIssuedKey monthExpiry = new ProviderIssuedKey(); monthExpiry.LoadOrCreate(aMember.Id.Value, email.Address, false, 1, true); string editUrl = HttpHost + "article/edit/" + anArticle.Id.Value + "/" + monthExpiry.IssuedKey; string activateUrl = HttpHost + "member/change_password/" + nonceIssuedKey.IssuedKey; string deleteUrl = HttpHost + "member/delete/" + nonceIssuedKey.IssuedKey; string submitState = ""; if (anArticle.IsPublished) { submitState = "Your article was submited to our system."; } else { submitState = "Your article was submited to our system as a draft."; } string category; if(anArticle.CategoryIds.Count > 0) { category = (new ProviderCategory(anArticle.CategoryIds[0])).Title; } else { category = "none"; } string emailBody = "DO NOT SHARE THIS E-MAIL OR REPLY TO THIS E-MAIL<br />" + "<br />" + "<br />" + submitState + "<br />" + "Id: "+anArticle.Id.Value.ToString()+"<br />" + "Title: "+anArticle.Title +"<br />" + "Category: " + category + "<br />" + "<br />" + "Click the link below to edit/delete your article at InsideWord:<br />" + "<a href='" + editUrl + "'>EDIT ARTICLE</a><br />" + "<br />"; if (!aMember.IsActive) { emailBody += "Click the link below to finish activating your account:<br />" + "<a href='" + activateUrl + "'>FINISH ACTIVATING ACCOUNT</a><br />" + "<br />" + "Don't know what this e-mail is about? Chances are someone used your e-mail by accident. Select the link below to delete the account:<br />" + "<a href='" + deleteUrl + "'>DELETE ACCOUNT</a><br />" + "<br />"; } emailBody += "<br />" + "<br />" + "<br />"; //+ DidYouKnow(); MailMessage aMailMessage = new MailMessage("*****@*****.**", email.Address, "InsideWord - edit article " + anArticle.Title, emailBody); aMailMessage.IsBodyHtml = true; DefaultSmtp.Send(aMailMessage); return true; }
/// <summary> /// Function to send an notification that the article was commented on /// </summary> /// <param name="anArticle">Article that was commented on</param> /// <param name="aMember">Member that will receive the e-mail</param> /// <returns>true if the e-mail was sent successfully and false otherwise.</returns> public bool SendCommentNotificationEmail(MailAddress email, ProviderArticle anArticle, ProviderMember commentAuthor) { string articleUrl = HttpHost + "article/" + anArticle.Id; string memberUrl = string.Empty; if (commentAuthor.IsAnonymous) { memberUrl = "Anonymous"; } else { memberUrl = "<a href='"+HttpHost + "member/profile/" + commentAuthor.Id.Value+"'>" + commentAuthor.DisplayName + "</a>"; } string emailBody = "DO NOT REPLY TO THIS E-MAIL<br />" + "<br />" + "<br />" + memberUrl + " has left a comment on your article, <a href='" + articleUrl + "'>" + anArticle.Title + "</a>" + "<br />" + "<br />" + "<br />"; //+ DidYouKnow(); MailMessage aMailMessage = new MailMessage("*****@*****.**", email.Address, "InsideWord - Someone commented on your article! " + anArticle.Title, emailBody); aMailMessage.IsBodyHtml = true; DefaultSmtp.Send(aMailMessage); return true; }
/// <summary> /// Function to help determine the owner of an article. If sufficient information is /// provided and the owner does not exist in the system then they will be created. /// </summary> /// <param name="model">view model containing the data of the new article</param> /// <param name="currentMember">the current member using the site</param> /// <returns>Returns a ProviderMember who is the owner of the article</returns> public static ProviderMember GetArticleOwner(ArticleEditorVM model, ProviderArticle anArticle, ProviderCurrentMember currentMember) { ProviderMember owningMember; if (anArticle.MemberId.HasValue) { owningMember = new ProviderMember(anArticle.MemberId.Value); } else if (anArticle.IsNew || !string.IsNullOrEmpty(model.ArticleEmail)) { // Have we been provided with an e-mail of the owner? if (!string.IsNullOrEmpty(model.ArticleEmail)) { MailAddress email = new MailAddress(model.ArticleEmail); long? memberId = ProviderEmail.FindOwner(email, true); if (memberId.HasValue) { // The owner already exists in our system so just retrieve them owningMember = new ProviderMember(memberId.Value); } else { // the owner doesn't exists so create them owningMember = new ProviderMember(); owningMember.CreateDate = DateTime.UtcNow; owningMember.EditDate = DateTime.UtcNow; owningMember.Save(); // attach the e-mail to this member ProviderEmail anEmail = new ProviderEmail(); anEmail.MemberId = owningMember.Id.Value; anEmail.IsValidated = false; anEmail.CreateDate = DateTime.UtcNow; anEmail.EditDate = DateTime.UtcNow; anEmail.Email = email; anEmail.Save(); } } else { // no e-mail provided so just use whoever is currently logged on, whether they be anonymous or not owningMember = currentMember; } } else { // this article has no owner so just return a blank member owningMember = new ProviderMember(); } return owningMember; }
protected void DelegateRefreshArticle(object sender, DoWorkEventArgs e) { InsideWordWebLog.Instance.Log.Debug("AsyncRefreshArticleManager.DelegateRefreshArticle(sender, e)"); while(_articleIdQueue.Count > 0) { List<string> tempErrorList = new List<string>(); ProviderArticle anArticle = new ProviderArticle(_articleIdQueue.Dequeue()); try { // Refresh it once to force re-parsing of the text anArticle.ForceRefresh(); // Associate the photos, but don't bother returning any errors. ArticleBL.AssociatePhotos(anArticle.ParsedText, anArticle, ref tempErrorList); if (tempErrorList.Count > 0) { InsideWordWebLog.Instance.Log.Debug(string.Join(", ", tempErrorList)); } // save it one more time to save the relationships anArticle.Save(); } catch (Exception caughtException) { tempErrorList.Add("article " + anArticle.Id.Value + " exception: " + caughtException); } ErrorList.AddRange(tempErrorList); _currentRefreshWorker.ReportProgress(_articleIdQueue.Count()); } Provider.DbCtx.DisposeCtx(); }
public bool Parse(ProviderArticle anArticle, ProviderCurrentMember currentMember) { ProviderMember author = anArticle.Author; string authorName = null; long? authorId = null; if (author != null) { authorId = author.Id; authorName = author.DisplayName; } else { authorName = null; } bool authorIsNull = string.IsNullOrEmpty(authorName); PageTitle = anArticle.Title + " by " + (authorIsNull ? "Anonymous" : authorName); RelatedHeadlinesByCategory = anArticle.RelatedHeadlinesByCategory(5); RelatedHeadlinesByAuthor = anArticle.RelatedHeadlinesByAuthor(3); ConversationList = anArticle.Conversations.ConvertAll<ConversationVM>(aConversation => new ConversationVM(aConversation, currentMember, authorId)); Article = new ArticleVM(anArticle, currentMember); return true; }
/// <summary> /// Function used to refresh the view model with any static data that may have been lost. /// This function is specifically used to refresh the model for a failed POST. /// </summary> /// <param name="anArticle">Article to refresh the data from</param> /// <param name="currentMember">Current member to refresh the data from</param> /// <param name="categoryList">Category list to refresh the data from</param> /// <returns>True if the function refreshed the model and false otherwise.</returns> public bool Refresh(ProviderArticle anArticle, ProviderCurrentMember currentMember, List<ProviderCategory> categoryList) { ArticleId = anArticle.Id; if (anArticle.IsNew) { PageTitle = "Publish Article"; } else { PageTitle = "Edit Article: "+anArticle.Title; } // till the article has been associated with someone, keep showing the e-mail input ShowEmailInput = !anArticle.MemberId.HasValue; List<KeyValuePair<long, string>> ddList = new List<KeyValuePair<long, string>>(); if (anArticle.CategoryIds.Count == 0) { ArticleCategoryId = -1; ddList.Add(_nullCategory); } else { ArticleCategoryId = anArticle.CategoryIds[0]; } ddList.AddRange(categoryList.ToDictionary(aCategory => aCategory.Id.Value, aCategory => aCategory.Title)); CategoryList = new SelectList(ddList, "key", "value", ArticleCategoryId); if (anArticle.IsPublished) { SaveState = SaveStates.Published; } else { SaveState = SaveStates.DraftAndContinue; } if (anArticle.CreateDate == DateTime.MinValue) { CreateDate = null; EditDate = null; } else { CreateDate = anArticle.CreateDate.ToShortDateString(); EditDate = anArticle.EditDate.ToShortDateString(); } return true; }
public virtual ActionResult ArticleEditor(long? articleId, ArticleEditorVM model, string submitType) { model.SaveButton = submitType; PartialPostVM returnValue = null; ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; ProviderArticle anArticle; if (articleId.HasValue) { anArticle = new ProviderArticle(articleId.Value); } else { anArticle = new ProviderArticle(); } List<string> errorList = new List<string>(); // Validate that the model is fine first and foremost to make sure we're not trying to work with bad data if (ModelState.IsValid) { ContentCheck result = null; if (!currentMember.IsSuperAdmin && anArticle.IsNew) { string email = string.Empty; string domain = string.Empty; if (currentMember.HasValidAltId(ProviderAlternateMemberId.AlternateType.Email)) { email = currentMember.Emails[0].Email.Address; } else if (!string.IsNullOrWhiteSpace(model.ArticleEmail)) { email = model.ArticleEmail; } if (currentMember.HasValidAltId(ProviderAlternateMemberId.AlternateType.Domain)) { domain = currentMember.Domains[0].Domain.AbsoluteUri; } // The mollom client crashes if passed in nbsp so strip those before sending it over string cleanedArticleBody = HtmlParser.StripSpecialChars(model.ArticleBody); MollomClient client = new MollomClient(InsideWordWebSettings.MollomPrivateKey, InsideWordWebSettings.MollomPublicKey); result = client.CheckContent(model.Title, cleanedArticleBody, currentMember.DisplayAdministrativeName, email, domain, HttpContext.Request.UserHostAddress); } if (result != null && result.Classification == ContentClassification.Spam) { ModelState.AddModelError("", "Your article has been blocked as spam."); } else if (result != null && result.Quality < InsideWordWebSettings.MollomArticleQuality) { ModelState.AddModelError("", "The quality of your article is too low. Try improving things such as spelling and grammar."); } else if (!currentMember.CanEdit(anArticle)) { returnValue = new PartialPostVM { Action = PartialPostVM.ActionType.redirect, Message = string.Empty, Content = Url.Action(MVC.Error.Index(401)) }; } else if (ArticleBL.Save(model, anArticle, ProviderCurrentMember.Instance, ref errorList) && (model.SaveState == ArticleEditorVM.SaveStates.DraftAndPreview || model.SaveState == ArticleEditorVM.SaveStates.Published)) { returnValue = new PartialPostVM { Action = PartialPostVM.ActionType.redirect, Message = string.Empty, Content = Url.Action(MVC.Article.ArticleDetails(anArticle.Id.Value)) }; } } if (returnValue == null) { foreach (string error in errorList) { ModelState.AddModelError("", error); } model.Refresh(anArticle, currentMember, ProviderCategory.Root.Children()); returnValue = new PartialPostVM { Action = PartialPostVM.ActionType.refresh, Message = string.Empty, Content = ControllerExtension.RenderPartialViewToString(this, MVC.Article.Views.ArticleEditor, (object)model) }; } return Json(returnValue); }
public virtual ActionResult ArticleEditor(long? articleId) { ActionResult returnValue = null; ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; if (!articleId.HasValue) { if (!currentMember.IsLoggedOn) { // Tried as hard as I could but we can't seem to use Outputcache for this controller // so we will cache it our way with a static. if (InsideWordWebStaticCache.Instance.NewArticleEditorView == null) { ArticleEditorVM viewModel = new ArticleEditorVM(); viewModel.Parse(ProviderCurrentMember.Instance, ProviderCategory.Root.Children()); InsideWordWebStaticCache.Instance.NewArticleEditorView = PartialView(viewModel); } returnValue = InsideWordWebStaticCache.Instance.NewArticleEditorView; } else { ArticleEditorVM viewModel = new ArticleEditorVM(); viewModel.Parse(ProviderCurrentMember.Instance, ProviderCategory.Root.Children()); returnValue = PartialView(viewModel); } } else { ProviderArticle anArticle = new ProviderArticle(articleId.Value); ArticleEditorVM viewModel = new ArticleEditorVM(); viewModel.Parse(anArticle, ProviderCurrentMember.Instance, ProviderCategory.Root.Children()); returnValue = PartialView(viewModel); } return returnValue; }
public virtual JsonResult PublishArticle(APIArticleVM model) { string from = "APILOGINFO - " + HttpContext.Request.UserHostAddress; InsideWordWebLog.Instance.Buffer(from, "PublishArticle( "+model+" )"); ApiMsgVM returnMessage = new ApiMsgVM( (int)ApiMsgVM.StatusEnum.failure ); ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; if (!currentMember.IsLoggedOn) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "You must be logged in to use this command. Use the API function " + Url.Action(MVC.API.Login()) + " to login."; } else if (!ModelState.IsValid) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "Could not parse the data."; } else if (string.IsNullOrWhiteSpace(model.Title) || string.IsNullOrWhiteSpace(model.Text)) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "title and text cannot be blank."; } else { ProviderArticle anArticle = null; ProviderAlternateArticleId altId = new ProviderAlternateArticleId(); if (model.Id.HasValue) { anArticle = new ProviderArticle(model.Id.Value); } else if (!string.IsNullOrWhiteSpace(model.AltId) && altId.Load(model.AltId, currentMember.Id.Value)) { anArticle = new ProviderArticle(altId.ArticleId); } else { anArticle = new ProviderArticle(); } if (!model.CategoryId.HasValue && anArticle.IsNew) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "New articles must have a Category Id"; } else if (model.CategoryId.HasValue && !ProviderCategory.Exists(model.CategoryId.Value)) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "The category id " + model.CategoryId + " does not exist."; } else if (!currentMember.CanEdit(anArticle)) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "You do not have the rights to edit article with InsideWord id " + anArticle.Id; if (string.IsNullOrWhiteSpace(model.AltId)) { returnMessage.StatusMessage += " and alternate id " + model.AltId; } } else { if (anArticle.IsNew) { anArticle.CreateDate = DateTime.UtcNow; } // The edit date is controlled by InsideWord and not the ones using the API // this is because edit date is actually rather important. anArticle.EditDate = DateTime.UtcNow; if (model.IsPublished.HasValue) { anArticle.IsPublished = model.IsPublished.Value; } else if (anArticle.IsNew) { anArticle.IsPublished = true; } anArticle.Blurb = model.Blurb; anArticle.Title = model.Title; anArticle.RawText = model.Text; anArticle.MemberId = currentMember.Id.Value; anArticle.RemoveAllCategories(); if (model.CategoryId.HasValue) { anArticle.AddCategory(model.CategoryId.Value); } else { anArticle.AddCategory(InsideWordSettingsDictionary.Instance.DefaultCategoryId.Value); } if (model.AlternateCategoryId.HasValue) { List<ProviderAlternateCategoryId> altCategoryList = currentMember.AlternateCategoryList; ProviderAlternateCategoryId alternateCategory = null; if (altCategoryList.Exists(altCat => altCat.AlternateId == model.AlternateCategoryId)) { alternateCategory = altCategoryList.Find(altCat => altCat.AlternateId == model.AlternateCategoryId); } else { // Doesn't seem to exist. This must be a new category we don't have any info on yet because the update from the client hasn't occurred yet. // Save this as an incomplete alternate category alternateCategory = new ProviderAlternateCategoryId(); alternateCategory.AlternateId = model.AlternateCategoryId.Value; alternateCategory.MemberId = currentMember.Id.Value; alternateCategory.Save(); } anArticle.RemoveAllAlternateCategories(); anArticle.AddAlternateCategory(alternateCategory.Id.Value); } // Associate the photos, but don't bother returning any errors. List<string> errorList = new List<string>(); ArticleBL.AssociatePhotos(model.Text, anArticle, ref errorList); if (errorList.Count > 0) { InsideWordWebLog.Instance.Log.Debug(string.Join(", ", errorList)); } anArticle.Save(); // now that the article is saved check if the model came in with an alternate id and if it did then try and create and attach. if (!string.IsNullOrWhiteSpace(model.AltId) && ProviderAlternateArticleId.Exists(model.AltId, currentMember.Id.Value) == null) { altId.MemberId = currentMember.Id.Value; altId.AlternateId = model.AltId; altId.ArticleId = anArticle.Id.Value; altId.Save(); } returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.success; returnMessage.StatusMessage = "Article has been submitted successfully."; returnMessage.Content = anArticle.Id.ToString(); } } InsideWordWebLog.Instance.Buffer(from, "Done PublishArticle - " + returnMessage); return Json(returnMessage); }
public virtual JsonResult ChangeArticleState(long articleId, InsideWordProvider.ProviderArticle.ArticleState state) { string from = "APILOGINFO - " + HttpContext.Request.UserHostAddress; InsideWordWebLog.Instance.Buffer(from, "ChangeArticleState(" + articleId + ", " + state.ToString() + ")"); ApiMsgVM returnMessage = new ApiMsgVM( (int)ApiMsgVM.StatusEnum.failure ); ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; ProviderArticle anArticle = new ProviderArticle(); if (!currentMember.IsLoggedOn) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "You must be logged in to use this command. Use the API function " + Url.Action(MVC.API.Login()) + " to login."; } else if (!anArticle.Load(articleId)) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "Could not change status. No article with id "+articleId; returnMessage.Content = String.Empty; } else if (!currentMember.CanEdit(anArticle)) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "Could not change status. Member does not have the rights to edit article " + articleId; returnMessage.Content = String.Empty; } else { bool returnMessageIsSet = false; anArticle.EditDate = DateTime.UtcNow; switch (state) { case ProviderArticle.ArticleState.delete: anArticle.IsHidden = true; anArticle.IsPublished = false; anArticle.Save(); break; case ProviderArticle.ArticleState.flagged: anArticle.IsHidden = true; anArticle.IsPublished = false; anArticle.Save(); break; case ProviderArticle.ArticleState.hidden: anArticle.IsHidden = true; anArticle.IsPublished = false; anArticle.Save(); break; case ProviderArticle.ArticleState.draft: anArticle.IsPublished = false; anArticle.Save(); break; case ProviderArticle.ArticleState.publish: anArticle.IsPublished = true; anArticle.Save(); break; default: returnMessageIsSet = true; returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.failure; returnMessage.StatusMessage = "Unknown status update "+state+" for article."; returnMessage.Content = String.Empty; break; } if (!returnMessageIsSet) { returnMessage.StatusCode = (int)ApiMsgVM.StatusEnum.success; returnMessage.StatusMessage = "Successfully updated article " + articleId + " status'."; returnMessage.Content = String.Empty; } } InsideWordWebLog.Instance.Buffer(from, "Done ChangeArticleState - " + returnMessage); return Json(returnMessage); }
public virtual JsonResult Vote(long articleId, long voteValue) { // direction: true = vote up, false = vote down AjaxReturnMsgVM viewModel = new AjaxReturnMsgVM { StatusCode = AjaxReturnMsgVM.Status.failure, StatusMessage = string.Empty, Content = string.Empty }; ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; if ( !currentMember.IsLoggedOn ) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.Content = "You must be logged on to vote."; } else if (!ProviderArticle.Exists(articleId)) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.Content = "The article you voted on no longer exists."; } else if(ProviderArticleVote.HasVoted(articleId, currentMember.Id.Value)) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.Content = "You have already voted on this article."; } else { ProviderArticleVote aVote = new ProviderArticleVote(); aVote.ArticleId = articleId; aVote.MemberId = currentMember.Id.Value; aVote.IsUpVote = voteValue > 0; aVote.IsDownVote = voteValue < 0; aVote.Save(); ProviderArticle anArticle = new ProviderArticle(articleId); viewModel.StatusCode = AjaxReturnMsgVM.Status.success; viewModel.Content = InsideWordUtility.FormatVotes(anArticle.CountVotes); ProviderMember author = anArticle.Author; if (aVote.IsUpVote && author != null && author.Id != currentMember.Id && author.HasValidAltId(ProviderAlternateMemberId.AlternateType.Email)) { // do some calculations to determine if we should send the e-mail int voteCount = anArticle.CountVotes; int n = (int)Math.Log((double)voteCount, 2); if (n < 0) { n = 0; } if (voteCount % (1 << n) == 0) { EmailManager.Instance.SendVoteNotificationEmail(author.Emails[0].Email, anArticle); } } } return Json(viewModel); }
public static JqGridResponse Delete(JqGridEditArticleVM model, ProviderCurrentMember currrentMember) { JqGridResponse aResponse = new JqGridResponse(); ProviderArticle anArticle = new ProviderArticle(model.Id); if (currrentMember.CanEdit(anArticle)) { if (anArticle.Delete()) { aResponse.Success = true; } else { aResponse.Success = false; aResponse.Message = ErrorStrings.OPERATION_FAILED; } } else { aResponse.Success = false; aResponse.Message = ErrorStrings.OPERATION_NO_RIGHTS; } return aResponse; }
public bool Parse(ProviderArticle anArticle) { if (anArticle.IsNew) { PageTitle = "Publish Article"; } else { ArticleId = anArticle.Id; PageTitle = "Edit Article: " + anArticle.Title; } return true; }
public bool Parse(ProviderArticle anArticle, ProviderCurrentMember currentMember, List<ProviderCategory> categoryList) { ArticleBody = anArticle.RawText; if (!anArticle.BlurbIsAutoGenerated) { Blurb = anArticle.Blurb; } Title = anArticle.Title; Refresh(anArticle, currentMember, categoryList); return true; }
public static bool Save(ArticleEditorVM model, ProviderArticle anArticle, ProviderCurrentMember currentMember, ref List<string> errorList) { bool returnValue = false; ProviderMember owningMember = GetArticleOwner(model, anArticle, currentMember); // IsNowClaimedArticle indicates if an article's state changed from unclaimed to now claimed bool IsNowClaimedArticle = anArticle.MemberId == null && owningMember.Id.HasValue; anArticle.MemberId = owningMember.Id; if (AssociatePhotos(model.ArticleBody, anArticle, ref errorList)) { if (owningMember.IsActive && !currentMember.IsLoggedOn) { // The owner is an active member but the current member is not logged in?! We're not sure if the member was lazy // and didn't bother to login or if this is a malicious person, so we will set IsPublished to false and treat // the article as a draft just to be safe. anArticle.IsPublished = false; } else if (model.SaveState == ArticleEditorVM.SaveStates.Published) { anArticle.IsPublished = true; } else if (model.SaveState == ArticleEditorVM.SaveStates.DraftAndContinue || model.SaveState == ArticleEditorVM.SaveStates.DraftAndPreview) { anArticle.IsPublished = false; } else { // defensive programming anArticle.IsPublished = false; } anArticle.Title = model.Title; anArticle.Blurb = model.Blurb; anArticle.RawText = model.ArticleBody; if (anArticle.IsNew) { anArticle.CreateDate = DateTime.UtcNow; } anArticle.EditDate = DateTime.UtcNow; // remove previous categories before adding new ones anArticle.RemoveAllCategories(); anArticle.AddCategory(model.ArticleCategoryId); // important that we fetch this info before we save because then the article is no longer new. bool isNew = anArticle.IsNew; anArticle.Save(); // if the current member is not logged on then save it in their workspace if (!currentMember.IsLoggedOn) { currentMember.CurrentWorkSpace.ArticleIdList.Add(anArticle.Id.Value); } // Send out an e-mail for the article only if it was claimed for the first time through e-mail // and the member is not active if (IsNowClaimedArticle && !string.IsNullOrEmpty(model.ArticleEmail) && !currentMember.IsActive) { EmailManager.Instance.SendEditArticleEmail(new MailAddress(model.ArticleEmail), anArticle, owningMember); } returnValue = true; } return returnValue; }
public ArticleEditVM(ProviderArticle anArticle) { Parse(anArticle); }
public virtual ActionResult ArticleEdit(long? articleId, string issuedKey) { ActionResult returnValue = null; ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; // If we have all of the required data then try an authentication with the issued key if (!currentMember.IsLoggedOn && !string.IsNullOrEmpty(issuedKey)) { List<string> errorList = new List<string>(); if (currentMember.Login(issuedKey, null, false, ref errorList) != ProviderCurrentMember.LoginEnum.success ) { // failed for whatever reason var viewModel = new MessageVM { Image = ImageLibrary.Alert, CssClassContainer = "failure", Message = "Failed to login: "******"Continue", LinkHref = Url.Action(MVC.Home.Index()), }; returnValue = View("Message", viewModel); } } if(returnValue == null) { ProviderArticle anArticle = null; if (articleId.HasValue) { anArticle = new ProviderArticle(articleId.Value); } else { anArticle = new ProviderArticle(); } if (!currentMember.CanEdit(anArticle)) { returnValue = RedirectToAction(MVC.Error.Index(401)); } else { returnValue = PartialView(new ArticleEditVM(anArticle)); } } return returnValue; }
public DetailsVM(ProviderArticle anArticle, ProviderCurrentMember currentMember) { Parse(anArticle, currentMember); }
public static void ParseNewMail() { // Retrieve newest e-mails List<long> uids = _emailClient.SearchFlag(Flag.Unseen); if (uids.Count > 0) { _log.Info("Processing " + uids.Count + " unseen message(s)."); ProviderMember aMember = new ProviderMember(); foreach (MessageInfo info in _emailClient.GetMessageInfoByUID(uids)) { _log.Info("Processing: " + info.Envelope.Sender + " / " + info.Envelope.From + " / " + info.Envelope.Subject); if (ValidEmail(info)) { // E-mail header seems good so far. // Fetch the owning member. aMember = GetEmailOwner(info); _log.Info("Checking account settings."); if (aMember.IsBanned) { _log.Info("Member is banned. Ignoring e-mail."); MailMessage aMailMessage = new MailMessage("donotreply@insideword", info.Envelope.From.ToString(), "insideword - article " + info.Envelope.Subject + " rejected", "DO NOT REPLY TO THIS E-MAIL<br />" + "The article you sent to us through e-mail was rejected because your account was banned."); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); } else { _log.Info("Member is good."); long articleId = -1; ProviderArticle anArticle = null; // Try parsing the subject. If we successfully parse it as a long then this is an update to that article if (long.TryParse(info.Envelope.Subject, out articleId)) { _log.Info("Subject was number " + articleId + ", so attempt to load the article for editing purposes."); if (ProviderArticle.Exists(articleId)) { // This article exists so load it anArticle = new ProviderArticle(articleId); _log.Info("Successfully loaded article " + articleId + " - " + anArticle.Title); } else { _log.Info("Article with id " + articleId + " doesn't exist. Ignoring e-mail."); MailMessage aMailMessage = new MailMessage("donotreply@insideword", info.Envelope.From.ToString(), "insideword - article rejected", "DO NOT REPLY TO THIS E-MAIL<br />" + "The article you sent to us through e-mail was rejected because you were trying to edit article " + articleId + ", which doesn't exist."); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); } } else { _log.Info("This is a new article."); anArticle = new ProviderArticle(); } if (anArticle != null) { _log.Info("Check member's edit rights for the given article."); if (!aMember.CanEdit(anArticle)) { _log.Info("Member does not have the rights to edit this article. Ignoring e-mail."); MailMessage aMailMessage = new MailMessage("donotreply@insideword", info.Envelope.From.ToString(), "insideword - article rejected", "DO NOT REPLY TO THIS E-MAIL<br />" + "The article you sent to us through e-mail was rejected because you do not have the rights to edit it!"); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); } else if (EditArticle(ref anArticle, aMember, info)) { MailAddress address = new MailAddress(info.Envelope.From.ToString()); EmailManager.Instance.SendEditArticleEmail(address, anArticle, aMember); } } } } _emailClient.MarkMessageSeen(info.MessageNumber); _log.Info("Marking message as seen"); _log.Info("Done processing: " + info.Envelope.Sender + " / " + info.Envelope.From + " / " + info.Envelope.Subject); } _ctxManager.DisposeCtx(); } }
public static bool EditArticle(ref ProviderArticle anArticle, ProviderMember aMember, MessageInfo info) { _log.Info("Populating article from e-mail"); bool returnValue = false; MailAddress senderAddress = new MailAddress(info.Envelope.Sender[0].Address); // Now parse the data from the e-mail EmailArticle anEmailArticle = new EmailArticle(info, _emailClient); if(anEmailArticle.IsHelp && !anEmailArticle.IsSubjectHelp) { // If we got the help command in the body but not in the subject then send the e-mail. // it's important that we check the subject help because otherwise we will send the help e-mail twice. _log.Info("Found the [help] command in the e-mail so respond with the help e-mail."); EmailManager.Instance.SendHelpEmail(senderAddress, aMember); } if (anEmailArticle.IsSubjectHelp) { // If we got help in the subject then ONLY send the help e-mail. Since the subject can't be an article title or id. _log.Info("This was a subject help request so send the help e-mail but do nothing else."); EmailManager.Instance.SendHelpEmail(senderAddress, aMember); } else { if(anEmailArticle.IsBlankEmail) { _log.Info("E-mail was completely blank"); } else if (anEmailArticle.Delete) { if (anArticle.IsNew) { _log.Info("Attempted to delete a new article, which makes no sense so ignore this e-mail."); MailMessage aMailMessage = new MailMessage("donotreply@insideword", senderAddress.Address, "insideword - article " + info.Envelope.Subject + " rejected", "DO NOT REPLY TO THIS E-MAIL<br />" + "The delete command you sent us in an e-mail was ignored since you tried to delete an article that doesn't exist. Be sure that you used the correct article id number in the subject."); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); } else { _log.Info("Deleting article."); string title = anArticle.Title; long id = anArticle.Id.Value; string result; if (anArticle.Delete()) { result = "Successfully deleted article " + title + " with id " + id; } else { result = "Failed to delete article " + title + " with id " + id; } _log.Info(result); MailMessage aMailMessage = new MailMessage("donotreply@insideword", senderAddress.Address, "insideword - article " + info.Envelope.Subject + " rejected", "DO NOT REPLY TO THIS E-MAIL<br />" + result + "<br />"); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); returnValue = false; } } else { if (anArticle.IsNew) { anArticle.CreateDate = DateTime.UtcNow; // only update the member id when we first create the article otherwise an admin could end up taking control when editing it. anArticle.MemberId = aMember.Id.Value; } anArticle.EditDate = DateTime.UtcNow; if (anArticle.IsNew || !string.IsNullOrWhiteSpace(anEmailArticle.Title)) { anArticle.Title = anEmailArticle.Title; } if (anEmailArticle.CategoryId.HasValue) { anArticle.AddCategory(anEmailArticle.CategoryId.Value); } if (anEmailArticle.Blurb != null) { if (string.IsNullOrWhiteSpace(anEmailArticle.Blurb)) { anArticle.Blurb = null; } else { anArticle.Blurb = anEmailArticle.Blurb; } } // don't overwrite unless we have some content. if (!string.IsNullOrWhiteSpace(anEmailArticle.Text)) { if (anArticle.IsNew || !anEmailArticle.Append) { anArticle.RawText = anEmailArticle.Text; } else { anArticle.RawText += anEmailArticle.Text; } } if (anEmailArticle.IsPublished.HasValue) { // if the e-mail specifically set the publish status then set it in the article anArticle.IsPublished = anEmailArticle.IsPublished.Value && anEmailArticle.CategoryId.HasValue; } else if (anArticle.IsNew) { // if the article is new but no status was set in the e-mail then set the status based on the following anArticle.IsPublished = anEmailArticle.CategoryId.HasValue; } else { // don't change the status of the article } anArticle.Save(); returnValue = true; } if (anEmailArticle.IsReadArticle) { if (anEmailArticle.ReadArticle.HasValue) { _log.Info("Request to send back article " + anEmailArticle.ReadArticle.Value); try { ProviderArticle aDifferentArticle = new ProviderArticle(anEmailArticle.ReadArticle.Value); if (aDifferentArticle.IsPublished || aMember.CanEdit(aDifferentArticle)) { EmailManager.Instance.SendArticleEmail(senderAddress, anArticle, aMember); } else { throw new Exception("Member doesn't have the rights to request article " + anEmailArticle.ReadArticle.Value); } } catch (Exception caughtException) { _log.Info("Failed to send back article " + anEmailArticle.ReadArticle.Value, caughtException); MailMessage aMailMessage = new MailMessage("donotreply@insideword", senderAddress.Address, "insideword - article request " + anEmailArticle.ReadArticle.Value + " failed", "DO NOT REPLY TO THIS E-MAIL<br />" + "Failed to return the article with id " + anEmailArticle.ReadArticle.Value + "<br />" + "Check to make sure the article id is a valid id.<br />"); aMailMessage.IsBodyHtml = true; EmailManager.Instance.DefaultSmtp.Send(aMailMessage); } } else { _log.Info("Sending back current article"); EmailManager.Instance.SendArticleEmail(senderAddress, anArticle, aMember); } } } return returnValue; }
/// <summary> /// Function to send an Edit/Delete e-mail to a member. /// </summary> /// <param name="anArticle">Article that member would like to edit/delete</param> /// <param name="aMember">Member that will receive the e-mail</param> /// <returns>true if the e-mail was sent successfully and false otherwise.</returns> public bool SendArticleEmail(MailAddress email, ProviderArticle anArticle, ProviderMember aMember) { string emailText = "[title " + anArticle.Title + "]<br />"; if (anArticle.IsPublished) { emailText += "[status publish]<br />"; } else { emailText += "[status draft]<br />"; } if (anArticle.CategoryIds.Count > 0) { emailText += "[category "+(new ProviderCategory(anArticle.CategoryIds[0])).Title+"]<br />"; } if (!anArticle.BlurbIsAutoGenerated) { emailText += "[blurb " + anArticle.Blurb+"]<br />"; } emailText += "<br />" + anArticle.ParsedText; MailMessage aMailMessage = new MailMessage("*****@*****.**", email.Address, anArticle.Id.ToString(), emailText); aMailMessage.IsBodyHtml = true; DefaultSmtp.Send(aMailMessage); return true; }
public virtual JsonResult AddComment(long articleId, string textComment, long? conversationId) { ProviderCurrentMember currentMember = ProviderCurrentMember.Instance; AjaxReturnMsgVM viewModel = new AjaxReturnMsgVM { StatusCode = AjaxReturnMsgVM.Status.success, StatusMessage = String.Empty }; ContentCheck result = null; if (!currentMember.IsSuperAdmin) { string email = string.Empty; string domain = string.Empty; if (currentMember.HasValidAltId(ProviderAlternateMemberId.AlternateType.Email)) { email = currentMember.Emails[0].Email.Address; } if (currentMember.HasValidAltId(ProviderAlternateMemberId.AlternateType.Domain)) { domain = currentMember.Domains[0].Domain.AbsoluteUri; } // The mollom client crashes if passed in special html chars ( ) so strip those before sending it over string cleanedTextComment = HtmlParser.StripSpecialChars(textComment); MollomClient client = new MollomClient(InsideWordWebSettings.MollomPrivateKey, InsideWordWebSettings.MollomPublicKey); result = client.CheckContent(string.Empty, cleanedTextComment, currentMember.DisplayAdministrativeName, email, domain, HttpContext.Request.UserHostAddress); } if (!currentMember.IsLoggedOn) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "You must be logged in to Comment."; } else if (!ProviderArticle.Exists(articleId)) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "The article you commented on no longer exists."; } else if(string.IsNullOrEmpty(textComment) || textComment.Length < 2) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "A comment needs more than 1 character."; } else if(textComment.Length > ProviderComment.TextSize) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "A comment can't be more than "+ProviderComment.TextSize+ " characters."; } else if (result != null && result.Classification == ContentClassification.Spam) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "Your comment has been blocked as spam."; } else if (result != null && result.Quality < InsideWordWebSettings.MollomCommentQuality) { viewModel.StatusCode = AjaxReturnMsgVM.Status.failure; viewModel.StatusMessage = "The quality of your comment is too low. Try improving things such as spelling and grammar."; } else { ProviderArticle anArticle = new ProviderArticle(articleId); ProviderConversation conversation; if (conversationId.HasValue) { conversation = new ProviderConversation(conversationId.Value); } else { conversation = new ProviderConversation(); } ProviderComment comment = new ProviderComment(); CommentBL.AddComment(textComment, currentMember, anArticle, ref conversation, ref comment); ProviderMember author = anArticle.Author; long? articleAuthorId = null; if (author != null) { articleAuthorId = author.Id; } bool isReply = conversation.Comments.Count > 1; if (isReply) { CommentVM commentVM = new CommentVM(comment, currentMember, articleAuthorId); commentVM.IsReply = isReply; viewModel.Content = ControllerExtension.RenderPartialViewToString(this, MVC.Child.Views.Comment, (object)commentVM); } else { ConversationVM conversationVM = new ConversationVM(conversation, ProviderCurrentMember.Instance, articleAuthorId); viewModel.Content = ControllerExtension.RenderPartialViewToString(this, MVC.Child.Views.Conversation, (object)conversationVM); } if (author != null && author.Id != currentMember.Id && author.HasValidAltId(ProviderAlternateMemberId.AlternateType.Email)) { // do some calculations to determine if we should send the e-mail int commentCount = anArticle.CountComments; int n = (int)Math.Log((double)commentCount, 2); if (n < 0) { n = 0; } if (commentCount % (1 << n) == 0) { EmailManager.Instance.SendCommentNotificationEmail(author.Emails[0].Email, anArticle, currentMember); } } } return Json(viewModel); }
public static JqGridResponse Edit(JqGridEditArticleVM model, ProviderCurrentMember currentMember) { JqGridResponse aResponse = new JqGridResponse(); ProviderArticle anArticle = new ProviderArticle(model.Id); if (currentMember.CanEdit(anArticle)) { anArticle.IgnoreFlags = model.IgnoreFlags; anArticle.IsHidden = model.IsHidden; anArticle.IsPublished = model.IsPublished; try { anArticle.Save(); aResponse.Success = true; } catch (Exception caughtException) { aResponse.Success = false; aResponse.Message = ErrorStrings.OPERATION_FAILED; } } else { aResponse.Success = false; aResponse.Message = ErrorStrings.OPERATION_NO_RIGHTS; } return aResponse; }