public async Task Create(IPage page) { await EnsureProjectSettings().ConfigureAwait(false); if (string.IsNullOrEmpty(page.Slug)) { var rootList = await GetRootPages().ConfigureAwait(false); if (rootList.Count == 0) { // no pages yet, creating first one so use default slug page.Slug = _settings.DefaultPageSlug; } else { var slug = ContentUtils.CreateSlug(page.Title); var available = await SlugIsAvailable(slug); while (!available) { slug = slug + "-"; available = await SlugIsAvailable(slug); } if (available) { page.Slug = slug; } } } await _pageCommands.Create(_settings.Id, page).ConfigureAwait(false); await _eventHandlers.HandleCreated(_settings.Id, page).ConfigureAwait(false); }
public async Task <bool> EditPost( string blogId, string postId, string userName, string password, PostStruct post, bool publish) { var existing = await blogService.GetPost( blogId, postId, userName, password ).ConfigureAwait(false); if (existing == null) { return(false); } var update = mapper.GetPostFromStruct(post); existing.Title = update.Title; existing.MetaDescription = update.MetaDescription; existing.Content = update.Content; // TODO: does OLW enable changing pubdate? //if (existing.PubDate != update.PubDate) //{ // await blogService.HandlePubDateAboutToChange(existing, update.PubDate).ConfigureAwait(false); // existing.PubDate = update.PubDate; //} if (!string.Equals(existing.Slug, update.Slug, StringComparison.OrdinalIgnoreCase)) { // slug changed make sure the new slug is available var requestedSlug = ContentUtils.CreateSlug(update.Slug); var available = await blogService.SlugIsAvailable(blogId, requestedSlug).ConfigureAwait(false); if (available) { existing.Slug = requestedSlug; } } existing.Categories = update.Categories; existing.IsPublished = publish; await blogService.Update( blogId, userName, password, existing, publish).ConfigureAwait(false); return(true); }
public async Task Create( IPage page, bool publish) { await EnsureProjectSettings().ConfigureAwait(false); if (publish) { page.PubDate = DateTime.UtcNow; } if (string.IsNullOrEmpty(page.Slug)) { var slug = ContentUtils.CreateSlug(page.Title); var available = await SlugIsAvailable(slug); if (available) { page.Slug = slug; } } var urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccesor.ActionContext); var imageAbsoluteBaseUrl = urlHelper.Content("~" + settings.LocalMediaVirtualPath); if (context != null) { imageAbsoluteBaseUrl = context.Request.AppBaseUrl() + settings.LocalMediaVirtualPath; } //this is no longer needed, we once used bootstrapwysiwyg which passed images as base64 content // but we don't use that anymore. now we have ckeditor and filemanager integration //page.Content = await mediaProcessor.ConvertBase64EmbeddedImagesToFilesWithUrls( // settings.LocalMediaVirtualPath, // page.Content // ).ConfigureAwait(false); var nonPublishedDate = new DateTime(1, 1, 1); if (page.PubDate == nonPublishedDate) { page.PubDate = DateTime.UtcNow; } await pageCommands.Create(settings.Id, page).ConfigureAwait(false); await eventHandlers.HandleCreated(settings.Id, page).ConfigureAwait(false); }
public async Task Create( IPage page, bool publish) { await EnsureProjectSettings().ConfigureAwait(false); if (publish) { page.PubDate = DateTime.UtcNow; } if (string.IsNullOrEmpty(page.Slug)) { var slug = ContentUtils.CreateSlug(page.Title); var available = await PageSlugIsAvailable(slug); if (available) { page.Slug = slug; } } var urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccesor.ActionContext); var imageAbsoluteBaseUrl = urlHelper.Content("~" + settings.LocalMediaVirtualPath); if (context != null) { imageAbsoluteBaseUrl = context.Request.AppBaseUrl() + settings.LocalMediaVirtualPath; } page.Content = await mediaProcessor.ConvertBase64EmbeddedImagesToFilesWithUrls( settings.LocalMediaVirtualPath, page.Content ).ConfigureAwait(false); var nonPublishedDate = new DateTime(1, 1, 1); if (page.PubDate == nonPublishedDate) { page.PubDate = DateTime.UtcNow; } await pageCommands.Create(settings.Id, page).ConfigureAwait(false); await eventHandlers.HandleCreated(settings.Id, page).ConfigureAwait(false); }
public async Task <CommandResult <IPage> > Handle(UpdateTemplatedPageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var page = request.Page; var history = page.CreateHistory(request.UserName); var project = await _projectService.GetProjectSettings(request.ProjectId); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(page.DraftSerializedModel)) { pageModelString = page.DraftSerializedModel; } else { pageModelString = page.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != page.Slug) { var slugIsAvailable = await _pageService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { errors.Add(_localizer["The page slug was not changed because the requested slug is already in use."]); request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); page.Title = request.ViewModel.Title; page.CorrelationKey = request.ViewModel.CorrelationKey; page.LastModified = DateTime.UtcNow; page.LastModifiedByUser = request.UserName; page.MenuFilters = request.ViewModel.MenuFilters; page.MetaDescription = request.ViewModel.MetaDescription; page.PageOrder = request.ViewModel.PageOrder; page.ShowHeading = request.ViewModel.ShowHeading; page.ShowMenu = request.ViewModel.ShowMenu; page.ShowComments = request.ViewModel.ShowComments; page.MenuFilters = request.ViewModel.MenuFilters; page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { page.Slug = request.ViewModel.Slug; } page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ParentSlug == project.DefaultPageSlug) { _log.LogWarning($"{request.UserName} tried to explicitely set the default page slug as the parent slug which is not allowed since all root pages are already children of the default page"); page.ParentSlug = string.Empty; page.ParentId = "0"; } var shouldFirePublishEvent = false; switch (request.ViewModel.SaveMode) { case SaveMode.SaveDraft: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishLater: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); page.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishNow: page.Author = request.ViewModel.Author; page.Content = renderedModel; page.SerializedModel = modelString; page.PubDate = DateTime.UtcNow; page.IsPublished = true; shouldFirePublishEvent = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftPubDate = null; page.DraftSerializedModel = null; break; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _pageService.Update(page); if (shouldFirePublishEvent) { await _pageService.FirePublishEvent(page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, page.Id).ConfigureAwait(false); } await _navigationCache.ClearTreeCache(); } return(new CommandResult <IPage>(page, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page from a content template failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public virtual async Task <IActionResult> Edit(PostEditViewModel model) { var project = await ProjectService.GetCurrentProjectSettings(); if (project == null) { Log.LogInformation("redirecting to index because project settings not found"); return(RedirectToRoute(BlogRoutes.BlogIndexRouteName)); } var canEdit = await User.CanEditPages(project.Id, AuthorizationService); if (!canEdit) { Log.LogInformation("redirecting to index because user is not allowed to edit"); return(RedirectToRoute(BlogRoutes.BlogIndexRouteName)); } if (!ModelState.IsValid) { if (string.IsNullOrEmpty(model.Id)) { ViewData["Title"] = StringLocalizer["New Post"]; } else { ViewData["Title"] = string.Format(CultureInfo.CurrentUICulture, StringLocalizer["Edit - {0}"], model.Title); } model.ProjectId = project.Id; model.TeasersEnabled = project.TeaserMode != TeaserMode.Off; return(View(model)); } var categories = new List <string>(); if (!string.IsNullOrEmpty(model.Categories)) { if (ContentOptions.ForceLowerCaseCategories) { categories = model.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = model.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } IPost post = null; if (!string.IsNullOrEmpty(model.Id)) { post = await BlogService.GetPost(model.Id); } var isNew = false; bool slugAvailable; string slug; if (post != null) { post.Title = model.Title; post.MetaDescription = model.MetaDescription; post.Content = model.Content; post.Categories = categories; if (model.Slug != post.Slug) { // remove any bad chars model.Slug = ContentUtils.CreateSlug(model.Slug); slugAvailable = await BlogService.SlugIsAvailable(project.Id, model.Slug); if (slugAvailable) { post.Slug = model.Slug; } else { //log.LogWarning($"slug {model.Slug} was requested but not changed because it is already in use"); this.AlertDanger(StringLocalizer["The post slug was not changed because the requested slug is already in use."], true); } } } else { isNew = true; if (!string.IsNullOrEmpty(model.Slug)) { // remove any bad chars model.Slug = ContentUtils.CreateSlug(model.Slug); slug = model.Slug; slugAvailable = await BlogService.SlugIsAvailable(project.Id, slug); if (!slugAvailable) { slug = ContentUtils.CreateSlug(model.Title); } } else { slug = ContentUtils.CreateSlug(model.Title); } slugAvailable = await BlogService.SlugIsAvailable(project.Id, slug); if (!slugAvailable) { //log.LogInformation("returning 409 because slug already in use"); ModelState.AddModelError("postediterror", StringLocalizer["slug is already in use."]); return(View(model)); } post = new Post() { BlogId = project.Id, Author = await AuthorNameResolver.GetAuthorName(User), Title = model.Title, MetaDescription = model.MetaDescription, Content = model.Content, Slug = slug , Categories = categories.ToList() }; } if (!string.IsNullOrEmpty(model.Author)) { post.Author = model.Author; } post.IsPublished = model.IsPublished; post.CorrelationKey = model.CorrelationKey; post.ImageUrl = model.ImageUrl; post.ThumbnailUrl = model.ThumbnailUrl; post.IsFeatured = model.IsFeatured; post.ContentType = model.ContentType; post.TeaserOverride = model.TeaserOverride; post.SuppressTeaser = model.SuppressTeaser; if (!string.IsNullOrEmpty(model.PubDate)) { var localTime = DateTime.Parse(model.PubDate); post.PubDate = TimeZoneHelper.ConvertToUtc(localTime, project.TimeZoneId); } if (isNew) { await BlogService.Create(post); } else { await BlogService.Update(post); } if (project.IncludePubDateInPostUrls) { return(RedirectToRoute(BlogRoutes.PostWithDateRouteName, new { year = post.PubDate.Year, month = post.PubDate.Month.ToString("00"), day = post.PubDate.Day.ToString("00"), slug = post.Slug })); } else { return(RedirectToRoute(BlogRoutes.PostWithoutDateRouteName, new { slug = post.Slug })); } }
public string CreateSlug(string title) { return(ContentUtils.CreateSlug(title)); }
public async Task <IActionResult> Edit(PageEditViewModel model) { if (!ModelState.IsValid) { if (string.IsNullOrEmpty(model.Id)) { ViewData["Title"] = sr["New Page"]; } else { ViewData["Title"] = string.Format(CultureInfo.CurrentUICulture, sr["Edit - {0}"], model.Title); } return(View(model)); } var project = await projectService.GetCurrentProjectSettings(); if (project == null) { log.LogInformation("redirecting to index because project settings not found"); return(RedirectToRoute(pageRoutes.PageRouteName)); } var canEdit = await User.CanEditPages(project.Id, authorizationService); if (!canEdit) { log.LogInformation("redirecting to index because user is not allowed to edit"); return(RedirectToRoute(pageRoutes.PageRouteName)); } IPage page = null; if (!string.IsNullOrEmpty(model.Id)) { page = await pageService.GetPage(model.Id); } var needToClearCache = false; var isNew = false; string slug = string.Empty;; bool slugIsAvailable = false; if (page != null) { if ((!string.IsNullOrEmpty(page.ViewRoles))) { if (!User.IsInRoles(page.ViewRoles)) { log.LogWarning($"page {page.Title} is protected by roles that user is not in so redirecting"); return(RedirectToRoute(pageRoutes.PageRouteName)); } } if (page.Title != model.Title) { needToClearCache = true; } page.Title = model.Title; page.MetaDescription = model.MetaDescription; page.Content = model.Content; if (page.IsPublished != model.IsPublished) { needToClearCache = true; } if (page.PageOrder != model.PageOrder) { needToClearCache = true; } if (!string.IsNullOrEmpty(model.Slug)) { // remove any bad characters model.Slug = ContentUtils.CreateSlug(model.Slug); if (model.Slug != page.Slug) { slugIsAvailable = await pageService.SlugIsAvailable(model.Slug); if (slugIsAvailable) { page.Slug = model.Slug; needToClearCache = true; } else { this.AlertDanger(sr["The page slug was not changed because the requested slug is already in use."], true); } } } } else { isNew = true; needToClearCache = true; if (!string.IsNullOrEmpty(model.Slug)) { // remove any bad chars model.Slug = ContentUtils.CreateSlug(model.Slug); slugIsAvailable = await pageService.SlugIsAvailable(model.Slug); if (slugIsAvailable) { slug = model.Slug; } } if (string.IsNullOrEmpty(slug)) { slug = ContentUtils.CreateSlug(model.Title); } slugIsAvailable = await pageService.SlugIsAvailable(slug); if (!slugIsAvailable) { model.DisqusShortname = project.DisqusShortName; //log.LogInformation("returning 409 because slug already in use"); ModelState.AddModelError("pageediterror", sr["slug is already in use."]); return(View(model)); } page = new Page() { ProjectId = project.Id, Author = await authorNameResolver.GetAuthorName(User), Title = model.Title, MetaDescription = model.MetaDescription, Content = model.Content, Slug = slug, ParentId = "0" //,Categories = categories.ToList() }; } if (!string.IsNullOrEmpty(model.ParentSlug)) { var parentPage = await pageService.GetPageBySlug(model.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; needToClearCache = true; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ViewRoles != model.ViewRoles) { needToClearCache = true; } page.ViewRoles = model.ViewRoles; page.CorrelationKey = model.CorrelationKey; page.PageOrder = model.PageOrder; page.IsPublished = model.IsPublished; page.ShowHeading = model.ShowHeading; page.ShowMenu = model.ShowMenu; page.MenuOnly = model.MenuOnly; page.ShowComments = model.ShowComments; if (page.MenuFilters != model.MenuFilters) { needToClearCache = true; } page.MenuFilters = model.MenuFilters; if (page.ExternalUrl != model.ExternalUrl) { needToClearCache = true; } page.ExternalUrl = model.ExternalUrl; if (!string.IsNullOrEmpty(model.Author)) { page.Author = model.Author; } if (!string.IsNullOrEmpty(model.PubDate)) { var localTime = DateTime.Parse(model.PubDate); page.PubDate = timeZoneHelper.ConvertToUtc(localTime, project.TimeZoneId); } if (page.ProjectId != project.Id) { page.ProjectId = project.Id; } if (isNew) { await pageService.Create(page, model.IsPublished); this.AlertSuccess(sr["The page was created successfully."], true); } else { await pageService.Update(page, model.IsPublished); this.AlertSuccess(sr["The page was updated successfully."], true); } if (needToClearCache) { pageService.ClearNavigationCache(); } if (page.Slug == project.DefaultPageSlug) { return(RedirectToRoute(pageRoutes.PageRouteName, new { slug = "" })); } if (!string.IsNullOrEmpty(page.ExternalUrl)) { this.AlertWarning(sr["Note that since this page has an override url, the menu item will link to the url so the page is used only as a means to add a link in the menu, the content is not used."], true); return(RedirectToRoute(pageRoutes.PageEditRouteName, new { slug = page.Slug })); } //var url = Url.RouteUrl(pageRoutes.PageRouteName, new { slug = page.Slug }); return(RedirectToRoute(pageRoutes.PageRouteName, new { slug = page.Slug })); //return Content(url); }
public async Task <CommandResult <IPost> > Handle(CreateOrUpdatePostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); try { bool isNew = false; var project = await _projectService.GetProjectSettings(request.ProjectId); var post = request.Post; ContentHistory history = null; if (post == null) { isNew = true; post = new Post() { BlogId = request.ProjectId, Title = request.ViewModel.Title, MetaDescription = request.ViewModel.MetaDescription, Slug = ContentUtils.CreateSlug(request.ViewModel.Title), CreatedByUser = request.UserName }; } else { history = post.CreateHistory(request.UserName); } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != post.Slug) { var slugIsAvailable = await _blogService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { post.Title = request.ViewModel.Title; post.CorrelationKey = request.ViewModel.CorrelationKey; post.ImageUrl = request.ViewModel.ImageUrl; post.ThumbnailUrl = request.ViewModel.ThumbnailUrl; post.IsFeatured = request.ViewModel.IsFeatured; post.ContentType = request.ViewModel.ContentType; post.TeaserOverride = request.ViewModel.TeaserOverride; post.SuppressTeaser = request.ViewModel.SuppressTeaser; post.LastModified = DateTime.UtcNow; post.LastModifiedByUser = request.UserName; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { post.Slug = request.ViewModel.Slug; } var categories = new List <string>(); if (!string.IsNullOrEmpty(request.ViewModel.Categories)) { if (_editOptions.ForceLowerCaseCategories) { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } post.Categories = categories; var shouldFirePublishEvent = false; switch (request.ViewModel.SaveMode) { case SaveMode.SaveDraft: post.DraftContent = request.ViewModel.Content; post.DraftAuthor = request.ViewModel.Author; break; case SaveMode.PublishLater: post.DraftContent = request.ViewModel.Content; post.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); post.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishNow: post.Content = request.ViewModel.Content; post.Author = request.ViewModel.Author; if (!post.PubDate.HasValue) { post.PubDate = DateTime.UtcNow; } else if (post.PubDate > DateTime.UtcNow) { post.PubDate = DateTime.UtcNow; } post.IsPublished = true; shouldFirePublishEvent = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftPubDate = null; break; } if (project.TeaserMode != TeaserMode.Off) { // need to generate the teaser on save string html = null; if (post.ContentType == "markdown") { var mdPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); html = Markdown.ToHtml(post.Content, mdPipeline); } else { html = post.Content; } var teaserResult = _teaserService.GenerateTeaser( project.TeaserTruncationMode, project.TeaserTruncationLength, html, Guid.NewGuid().ToString(),//cache key post.Slug, project.LanguageCode, false //logWarnings ); post.AutoTeaser = teaserResult.Content; } if (history != null) { await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); } if (isNew) { await _blogService.Create(post); } else { await _blogService.Update(post); } if (shouldFirePublishEvent) { await _blogService.FirePublishEvent(post); await _historyCommands.DeleteDraftHistory(request.ProjectId, post.Id).ConfigureAwait(false); } } return(new CommandResult <IPost>(post, request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task Create( string projectId, string userName, string password, IPage page, bool publish) { var permission = await security.ValidatePermissions( projectId, userName, password, CancellationToken ).ConfigureAwait(false); if (!permission.CanEditPosts) { return; } var settings = await projectService.GetProjectSettings(projectId).ConfigureAwait(false); if (publish) { page.PubDate = DateTime.UtcNow; } if (string.IsNullOrEmpty(page.Slug)) { var slug = ContentUtils.CreateSlug(page.Title); var available = await SlugIsAvailable(slug); if (available) { page.Slug = slug; } } var urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccesor.ActionContext); var imageAbsoluteBaseUrl = urlHelper.Content("~" + settings.LocalMediaVirtualPath); if (context != null) { imageAbsoluteBaseUrl = context.Request.AppBaseUrl() + settings.LocalMediaVirtualPath; } // open live writer passes in posts with absolute urls // we want to change them to relative to keep the files portable // to a different root url page.Content = await _contentProcessor.ConvertMediaUrlsToRelative( settings.LocalMediaVirtualPath, imageAbsoluteBaseUrl, //this shold be resolved from virtual using urlhelper page.Content); // olw also adds hard coded style to images page.Content = _contentProcessor.RemoveImageStyleAttribute(page.Content); // here we need to process any base64 embedded images // save them under wwwroot // and update the src in the post with the new url // since this overload of Save is only called from metaweblog // and metaweblog does not base64 encode the images like the browser client // this call may not be needed here //await mediaProcessor.ConvertBase64EmbeddedImagesToFilesWithUrls( // settings.LocalMediaVirtualPath, // post // ).ConfigureAwait(false); var nonPublishedDate = new DateTime(1, 1, 1); if (page.PubDate == nonPublishedDate) { page.PubDate = DateTime.UtcNow; } await pageCommands.Create(projectId, page).ConfigureAwait(false); await eventHandlers.HandleCreated(projectId, page).ConfigureAwait(false); }
public async Task <IActionResult> AjaxPost(PageEditViewModel model) { // disable status code page for ajax requests var statusCodePagesFeature = HttpContext.Features.Get <IStatusCodePagesFeature>(); if (statusCodePagesFeature != null) { statusCodePagesFeature.Enabled = false; } if (string.IsNullOrEmpty(model.Title)) { // if a page has been configured to not show the title // this may be null on edit, if it is a new page then it should be required // because it is used for generating the slug //if (string.IsNullOrEmpty(model.Slug)) //{ log.LogInformation("returning 500 because no title was posted"); return(StatusCode(500)); //} } var project = await projectService.GetCurrentProjectSettings(); if (project == null) { log.LogInformation("returning 500 blog not found"); return(StatusCode(500)); } var canEdit = await User.CanEditPages(project.Id, authorizationService); if (!canEdit) { log.LogInformation("returning 403 user is not allowed to edit"); return(StatusCode(403)); } //string[] categories = new string[0]; //if (!string.IsNullOrEmpty(model.Categories)) //{ // categories = model.Categories.Split(new char[] { ',' }, // StringSplitOptions.RemoveEmptyEntries); //} IPage page = null; if (!string.IsNullOrEmpty(model.Id)) { page = await pageService.GetPage(model.Id); } var needToClearCache = false; var isNew = false; if (page != null) { page.Title = model.Title; page.MetaDescription = model.MetaDescription; page.Content = model.Content; if (page.PageOrder != model.PageOrder) { needToClearCache = true; } } else { isNew = true; needToClearCache = true; var slug = ContentUtils.CreateSlug(model.Title); var available = await pageService.SlugIsAvailable(project.Id, slug); if (!available) { log.LogInformation("returning 409 because slug already in use"); return(StatusCode(409)); } page = new Page() { ProjectId = project.Id, Author = User.GetUserDisplayName(), Title = model.Title, MetaDescription = model.MetaDescription, Content = model.Content, Slug = slug, ParentId = "0" //,Categories = categories.ToList() }; } if (!string.IsNullOrEmpty(model.ParentSlug)) { var parentPage = await pageService.GetPageBySlug(project.Id, model.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; needToClearCache = true; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ViewRoles != model.ViewRoles) { needToClearCache = true; } page.ViewRoles = model.ViewRoles; page.PageOrder = model.PageOrder; page.IsPublished = model.IsPublished; page.ShowHeading = model.ShowHeading; if (!string.IsNullOrEmpty(model.PubDate)) { var localTime = DateTime.Parse(model.PubDate); page.PubDate = timeZoneHelper.ConvertToUtc(localTime, project.TimeZoneId); } if (isNew) { await pageService.Create(page, model.IsPublished); } else { await pageService.Update(page, model.IsPublished); } if (needToClearCache) { pageService.ClearNavigationCache(); } var url = Url.Action("Index", "Page", new { slug = page.Slug }); return(Content(url)); }
public async Task <CommandResult <IPage> > Handle(CreateOrUpdatePageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); try { bool isNew = false; var project = await _projectService.GetProjectSettings(request.ProjectId); var page = request.Page; ContentHistory history = null; if (page == null) { isNew = true; page = new Page() { ProjectId = request.ProjectId, ParentId = "0", CreatedByUser = request.UserName, Slug = ContentUtils.CreateSlug(request.ViewModel.Title), ContentType = request.ViewModel.ContentType }; } else { history = page.CreateHistory(request.UserName); } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != page.Slug) { var slugIsAvailable = await _pageService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { errors.Add(_localizer["The page slug was invalid because the requested slug is already in use."]); request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { page.Title = request.ViewModel.Title; page.CorrelationKey = request.ViewModel.CorrelationKey; page.LastModified = DateTime.UtcNow; page.LastModifiedByUser = request.UserName; page.MenuFilters = request.ViewModel.MenuFilters; page.MetaDescription = request.ViewModel.MetaDescription; page.PageOrder = request.ViewModel.PageOrder; page.ShowHeading = request.ViewModel.ShowHeading; page.ShowMenu = request.ViewModel.ShowMenu; page.MenuOnly = request.ViewModel.MenuOnly; page.DisableEditor = request.ViewModel.DisableEditor; page.ShowComments = request.ViewModel.ShowComments; page.MenuFilters = request.ViewModel.MenuFilters; page.ExternalUrl = request.ViewModel.ExternalUrl; page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { page.Slug = request.ViewModel.Slug; } if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ParentSlug == project.DefaultPageSlug) { _log.LogWarning($"{request.UserName} tried to explicitely set the default page slug as the parent slug which is not allowed since all root pages are already children of the default page"); page.ParentSlug = string.Empty; page.ParentId = "0"; } var shouldFirePublishEvent = false; //var shouldFireUnPublishEvent = false; switch (request.ViewModel.SaveMode) { //case SaveMode.UnPublish: // page.DraftContent = request.ViewModel.Content; // page.DraftAuthor = request.ViewModel.Author; // page.DraftPubDate = null; // page.IsPublished = false; // page.PubDate = null; // shouldFireUnPublishEvent = true; // break; case SaveMode.SaveDraft: page.DraftContent = request.ViewModel.Content; page.DraftAuthor = request.ViewModel.Author; // should we clear the draft pub date if save draft clicked? //page.DraftPubDate = null; if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishLater: page.DraftContent = request.ViewModel.Content; page.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); page.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishNow: page.Content = request.ViewModel.Content; page.Author = request.ViewModel.Author; page.PubDate = DateTime.UtcNow; page.IsPublished = true; shouldFirePublishEvent = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftPubDate = null; break; } if (history != null) { await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); } if (isNew) { await _pageService.Create(page); } else { await _pageService.Update(page); } if (shouldFirePublishEvent) { await _pageService.FirePublishEvent(page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, page.Id).ConfigureAwait(false); } //if (shouldFireUnPublishEvent) //{ // await _pageService.FireUnPublishEvent(page).ConfigureAwait(false); //} _pageService.ClearNavigationCache(); } return(new CommandResult <IPage>(page, request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public async Task <CommandResult <IPost> > Handle(UpdateTemplatedPostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var post = request.Post; var history = post.CreateHistory(request.UserName); var project = await _projectService.GetCurrentProjectSettings(); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(post.DraftSerializedModel)) { pageModelString = post.DraftSerializedModel; } else { pageModelString = post.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != post.Slug) { var slug = request.ViewModel.Slug; var slugIsAvailable = await _blogService.SlugIsAvailable(slug); while (!slugIsAvailable) { slug += "-"; slugIsAvailable = await _blogService.SlugIsAvailable(slug); } if (slugIsAvailable) { post.Slug = slug; } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); post.Title = request.ViewModel.Title; post.CorrelationKey = request.ViewModel.CorrelationKey; post.ImageUrl = request.ViewModel.ImageUrl; post.ThumbnailUrl = request.ViewModel.ThumbnailUrl; post.IsFeatured = request.ViewModel.IsFeatured; post.TeaserOverride = request.ViewModel.TeaserOverride; post.SuppressTeaser = request.ViewModel.SuppressTeaser; post.ShowComments = request.ViewModel.ShowComments; post.LastModified = DateTime.UtcNow; post.LastModifiedByUser = request.UserName; post.MetaDescription = request.ViewModel.MetaDescription; var categories = new List <string>(); if (!string.IsNullOrEmpty(request.ViewModel.Categories)) { if (_editOptions.ForceLowerCaseCategories) { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } post.Categories = categories; var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); var shouldFirePublishEvent = false; var saveMode = request.ViewModel.SaveMode; if (saveMode == SaveMode.PublishLater) { if (request.ViewModel.NewPubDate.HasValue) { var newPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); if (newPubDate < DateTime.UtcNow) { saveMode = SaveMode.PublishNow; post.PubDate = newPubDate; } } } switch (saveMode) { case SaveMode.SaveDraft: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishLater: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { post.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishNow: post.Author = request.ViewModel.Author; post.Content = renderedModel; post.SerializedModel = modelString; if (!post.PubDate.HasValue) { post.PubDate = DateTime.UtcNow; } post.IsPublished = true; shouldFirePublishEvent = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftPubDate = null; post.DraftSerializedModel = null; break; } if (project.TeaserMode != TeaserMode.Off) { // need to generate the teaser on save var teaserResult = _teaserService.GenerateTeaser( project.TeaserTruncationMode, project.TeaserTruncationLength, post.Content, Guid.NewGuid().ToString(),//cache key post.Slug, project.LanguageCode, false //logWarnings ); post.AutoTeaser = teaserResult.Content; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _blogService.Update(post); if (shouldFirePublishEvent) { await _blogService.FirePublishEvent(post).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, post.Id).ConfigureAwait(false); } } return(new CommandResult <IPost>(post, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a post from a content template failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task <bool> EditPost( string blogId, string postId, string userName, string password, PostStruct post, bool publish) { var permission = await _security.ValidatePermissions( blogId, userName, password, CancellationToken.None ).ConfigureAwait(false); if (!permission.CanEditPosts) { _log.LogWarning($"rejecting new post because user {userName} cannot edit posts"); return(false); } var existing = await _blogService.GetPost(postId).ConfigureAwait(false); if (existing == null) { _log.LogError($"post not found for id {postId}"); return(false); } if (!string.IsNullOrWhiteSpace(existing.TemplateKey)) { _log.LogError($"post {postId} uses a content template and cannot be edited via metaweblog api"); return(false); } if (existing.ContentType != ProjectConstants.HtmlContentType) { _log.LogError($"post {postId} uses a content type {existing.ContentType} and cannot be edited via metaweblog api"); return(false); } var history = existing.CreateHistory(userName); var update = _mapper.GetPostFromStruct(post); existing.Title = update.Title; existing.MetaDescription = update.MetaDescription; existing.LastModified = DateTime.UtcNow; existing.LastModifiedByUser = permission.DisplayName; if (!string.Equals(existing.Slug, update.Slug, StringComparison.OrdinalIgnoreCase)) { // slug changed make sure the new slug is available var requestedSlug = ContentUtils.CreateSlug(update.Slug); var available = await _blogService.SlugIsAvailable(blogId, requestedSlug).ConfigureAwait(false); if (available) { existing.Slug = requestedSlug; } } existing.Categories = update.Categories; if (publish) { existing.Content = update.Content; existing.IsPublished = true; if (!existing.PubDate.HasValue) { existing.PubDate = DateTime.UtcNow; } existing.DraftAuthor = null; existing.DraftContent = null; existing.DraftPubDate = null; } else { existing.DraftContent = update.Content; } var convertToRelativeUrls = true; await _blogService.Update(existing, convertToRelativeUrls).ConfigureAwait(false); await _contentHistoryCommands.Create(blogId, history); if (publish) { await _blogService.FirePublishEvent(existing); await _contentHistoryCommands.DeleteDraftHistory(blogId, history.ContentId); } return(true); }