Exemple #1
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>True if deleted successfully and False otherwise.</returns>
        public bool Execute(DeletePageContentCommandRequest request)
        {
            UnitOfWork.BeginTransaction();

            var pageContent = Repository.AsQueryable <PageContent>()
                              .Where(f => f.Id == request.PageContentId)
                              .Fetch(f => f.Content)
                              .Fetch(f => f.Page)
                              .FirstOne();

            var htmlContent = pageContent.Content as HtmlContent;

            if (htmlContent != null)
            {
                // Check if user has confirmed the deletion of content
                if (!request.IsUserConfirmed && pageContent.Page.IsMasterPage)
                {
                    var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(pageContent.Page.Id, pageContent.Content.Id);
                    if (hasAnyChildren)
                    {
                        var message    = PagesGlobalization.DeletePageContent_ContentHasChildrenContents_DeleteConfirmationMessage;
                        var logMessage = string.Format("User is trying to delete content which has children contents. Confirmation is required. PageContentId: {0}, ContentId: {1}, PageId: {2}",
                                                       request.PageContentId, pageContent.Page.Id, pageContent.Content.Id);
                        throw new ConfirmationRequestException(() => message, logMessage);
                    }
                }

                var draft = pageContent.Content.History != null?pageContent.Content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) : null;

                if (draft != null)
                {
                    Repository.Delete <HtmlContent>(draft.Id, request.ContentVersion);
                    Repository.Delete <HtmlContent>(pageContent.Content.Id, pageContent.Content.Version);
                }
                else
                {
                    Repository.Delete <HtmlContent>(pageContent.Content.Id, request.ContentVersion);
                }
            }

            if (pageContent.Options != null)
            {
                foreach (var option in pageContent.Options)
                {
                    Repository.Delete(option);
                }
            }

            Repository.Delete <PageContent>(pageContent.Id, request.PageContentVersion);
            UnitOfWork.Commit();

            // Notify
            Events.PageEvents.Instance.OnPageContentDeleted(pageContent);
            if (htmlContent != null)
            {
                Events.PageEvents.Instance.OnHtmlContentDeleted(htmlContent);
            }

            return(true);
        }
        protected virtual void GetBlogPostAndContentEntities(BlogPostViewModel request, IPrincipal principal, string[] roles,
                                                             ref bool isNew, out BlogPostContent content, out PageContent pageContent, out BlogPost blogPost)
        {
            content     = null;
            pageContent = null;

            // Loading blog post and it's content, or creating new, if such not exists
            if (!isNew)
            {
                var blogPostFuture = repository
                                     .AsQueryable <BlogPost>(b => b.Id == request.Id)
                                     .ToFuture();

                content = repository
                          .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted))
                          .ToFuture()
                          .FirstOrDefault();

                blogPost = blogPostFuture.FirstOne();

                if (configuration.Security.AccessControlEnabled)
                {
                    accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles);
                }

                if (content != null)
                {
                    // Check if user has confirmed the deletion of content
                    if (!request.IsUserConfirmed && blogPost.IsMasterPage)
                    {
                        var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(blogPost.Id, content.Id, request.Content);
                        if (hasAnyChildren)
                        {
                            var message    = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage;
                            var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. ContentId: {0}, PageId: {1}",
                                                           content.Id, blogPost.Id);
                            throw new ConfirmationRequestException(() => message, logMessage);
                        }
                    }

                    var bpRef      = blogPost;
                    var contentRef = content;
                    pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == bpRef && !c.IsDeleted && c.Content == contentRef);
                }
            }
            else
            {
                blogPost = new BlogPost();
            }

            if (pageContent == null)
            {
                pageContent = new PageContent {
                    Page = blogPost
                };
            }
        }
Exemple #3
0
        /// <summary>
        /// Saves the blog post.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="principal">The principal.</param>
        /// <returns>
        /// Saved blog post entity
        /// </returns>
        public BlogPost SaveBlogPost(BlogPostViewModel request, IPrincipal principal)
        {
            string[] roles;
            if (request.DesirableStatus == ContentStatus.Published)
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent);
                roles = new[] { RootModuleConstants.UserRoles.PublishContent };
            }
            else
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent);
                roles = new[] { RootModuleConstants.UserRoles.EditContent };
            }

            Layout layout;
            Page   masterPage;

            LoadLayout(out layout, out masterPage);

            if (masterPage != null)
            {
                var level = accessControlService.GetAccessLevel(masterPage, principal);
                if (level < AccessLevel.Read)
                {
                    var          message    = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage;
                    const string logMessage = "Failed to save blog post. Selected master page for page layout is inaccessible.";
                    throw new ValidationException(() => message, logMessage);
                }
            }

            var region      = LoadRegion(layout, masterPage);
            var isNew       = request.Id.HasDefaultValue();
            var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent);

            // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception.

            BlogPost        blogPost;
            BlogPostContent content     = null;
            PageContent     pageContent = null;

            Pages.Models.Redirect redirectCreated = null;

            // Loading blog post and it's content, or creating new, if such not exists
            if (!isNew)
            {
                var blogPostFuture = repository
                                     .AsQueryable <BlogPost>(b => b.Id == request.Id)
                                     .ToFuture();

                content = repository
                          .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted))
                          .ToFuture()
                          .FirstOrDefault();

                blogPost = blogPostFuture.FirstOne();

                if (cmsConfiguration.Security.AccessControlEnabled)
                {
                    accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles);
                }

                if (content != null)
                {
                    // Check if user has confirmed the deletion of content
                    if (!request.IsUserConfirmed && blogPost.IsMasterPage)
                    {
                        var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(blogPost.Id, content.Id, request.Content);
                        if (hasAnyChildren)
                        {
                            var message    = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage;
                            var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. ContentId: {0}, PageId: {1}",
                                                           content.Id, blogPost.Id);
                            throw new ConfirmationRequestException(() => message, logMessage);
                        }
                    }

                    pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == blogPost && !c.IsDeleted && c.Content == content);
                }

                if (userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && request.BlogUrl != null)
                {
                    request.BlogUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(request.BlogUrl, request.Id);
                    if (request.RedirectFromOldUrl)
                    {
                        var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl);
                        if (redirect != null)
                        {
                            repository.Save(redirect);
                            redirectCreated = redirect;
                        }
                    }

                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                }
            }
            else
            {
                blogPost = new BlogPost();
            }

            if (pageContent == null)
            {
                pageContent = new PageContent {
                    Region = region, Page = blogPost
                };
            }

            // Push to change modified data each time.
            blogPost.ModifiedOn = DateTime.Now;
            blogPost.Version    = request.Version;

            if (userCanEdit)
            {
                blogPost.Title       = request.Title;
                blogPost.Description = request.IntroText;
                blogPost.Author      = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null;
                blogPost.Category    = request.CategoryId.HasValue ? repository.AsProxy <Category>(request.CategoryId.Value) : null;
                blogPost.Image       = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                if (isNew || request.DesirableStatus == ContentStatus.Published)
                {
                    blogPost.ActivationDate = request.LiveFromDate;
                    blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate);
                }
            }

            if (isNew)
            {
                if (!string.IsNullOrWhiteSpace(request.BlogUrl))
                {
                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(blogPost.PageUrl);
                }
                else
                {
                    blogPost.PageUrl = CreateBlogPermalink(request.Title);
                }

                blogPost.MetaTitle = request.MetaTitle ?? request.Title;
                if (masterPage != null)
                {
                    blogPost.MasterPage = masterPage;
                    masterPageService.SetPageMasterPages(blogPost, masterPage.Id);
                }
                else
                {
                    blogPost.Layout = layout;
                }
                UpdateStatus(blogPost, request.DesirableStatus);
                AddDefaultAccessRules(blogPost, principal, masterPage);
            }
            else if (request.DesirableStatus == ContentStatus.Published ||
                     blogPost.Status == PageStatus.Preview)
            {
                // Update only if publishing or current status is preview.
                // Else do not change, because it may change from published to draft status
                UpdateStatus(blogPost, request.DesirableStatus);
            }

            // Create content.
            var newContent = new BlogPostContent
            {
                Id               = content != null ? content.Id : Guid.Empty,
                Name             = request.Title,
                Html             = request.Content ?? string.Empty,
                EditInSourceMode = request.EditInSourceMode,
                ActivationDate   = request.LiveFromDate,
                ExpirationDate   = TimeHelper.FormatEndDate(request.LiveToDate)
            };

            // Preserve content if user is not authorized to change it.
            if (!userCanEdit)
            {
                if (content == null)
                {
                    throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content.
                }

                var contentToPublish = (BlogPostContent)(content.History != null
                    ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content
                    : content);

                newContent.Name = contentToPublish.Name;
                newContent.Html = contentToPublish.Html;
            }

            content             = (BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus);
            pageContent.Content = content;

            blogPost.PageUrlHash     = blogPost.PageUrl.UrlHash();
            blogPost.UseCanonicalUrl = request.UseCanonicalUrl;

            repository.Save(blogPost);
            repository.Save(content);
            repository.Save(pageContent);

            pageContent.Content   = content;
            blogPost.PageContents = new [] { pageContent };

            IList <Tag> newTags = null;

            if (userCanEdit)
            {
                tagService.SavePageTags(blogPost, request.Tags, out newTags);
            }

            // Commit
            unitOfWork.Commit();

            // Notify about new or updated blog post.
            if (isNew)
            {
                Events.BlogEvents.Instance.OnBlogCreated(blogPost);
            }
            else
            {
                Events.BlogEvents.Instance.OnBlogUpdated(blogPost);
            }

            // Notify about new created tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            return(blogPost);
        }
        public SavePageHtmlContentResponse Execute(SavePageHtmlContentCommandRequest request)
        {
            var model = request.Content;

            if (model.DesirableStatus == ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent);
            }

            if (model.Id == default(Guid) || model.DesirableStatus != ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent);
            }

            PageContent pageContent;
            var         isNew = model.Id.HasDefaultValue();

            if (!isNew)
            {
                var query = Repository
                            .AsQueryable <PageContent>()
                            .Where(f => f.Id == model.Id && !f.IsDeleted)
                            .AsQueryable();

                if (!model.IsUserConfirmed)
                {
                    query = query.Fetch(f => f.Page);
                }

                if (configuration.Security.AccessControlEnabled)
                {
                    query = query.Fetch(f => f.Page).ThenFetchMany(f => f.AccessRules);
                }

                pageContent = query.ToList().FirstOne();

                // Check if user has confirmed the deletion of content
                if (!model.IsUserConfirmed && pageContent.Page.IsMasterPage)
                {
                    var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(model.PageId, model.ContentId, model.PageContent);
                    if (hasAnyChildren)
                    {
                        var message    = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage;
                        var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. PageContentId: {0}, ContentId: {1}, PageId: {2}",
                                                       model.Id, model.ContentId, model.PageId);
                        throw new ConfirmationRequestException(() => message, logMessage);
                    }
                }
            }
            else
            {
                pageContent       = new PageContent();
                pageContent.Order = contentService.GetPageContentNextOrderNumber(model.PageId);

                if (configuration.Security.AccessControlEnabled)
                {
                    pageContent.Page = Repository
                                       .AsQueryable <Root.Models.Page>(p => p.Id == model.PageId)
                                       .FetchMany(p => p.AccessRules)
                                       .ToList()
                                       .FirstOne();
                }
            }

            // Demand access
            if (configuration.Security.AccessControlEnabled)
            {
                AccessControlService.DemandAccess(pageContent.Page, Context.Principal, AccessLevel.ReadWrite);
            }

            // Get page as proxy, if page is not retrieved yet
            if (!configuration.Security.AccessControlEnabled)
            {
                pageContent.Page = Repository.AsProxy <Root.Models.Page>(model.PageId);
            }
            pageContent.Region = Repository.AsProxy <Region>(model.RegionId);

            var contentToSave = new HtmlContent
            {
                Id               = model.ContentId,
                ActivationDate   = model.LiveFrom,
                ExpirationDate   = TimeHelper.FormatEndDate(model.LiveTo),
                Name             = model.ContentName,
                Html             = model.PageContent ?? string.Empty,
                UseCustomCss     = model.EnabledCustomCss,
                CustomCss        = model.CustomCss,
                UseCustomJs      = model.EanbledCustomJs,
                CustomJs         = model.CustomJs,
                EditInSourceMode = model.EditInSourceMode
            };

            // Preserve content if user is not authorized to change it.
            if (!SecurityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent) && model.Id != default(Guid))
            {
                var originalContent  = Repository.First <HtmlContent>(model.ContentId);
                var contentToPublish = (HtmlContent)(originalContent.History != null
                    ? originalContent.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? originalContent
                    : originalContent);

                contentToSave.Name             = contentToPublish.Name;
                contentToSave.Html             = contentToPublish.Html;
                contentToSave.UseCustomCss     = contentToPublish.UseCustomCss;
                contentToSave.CustomCss        = contentToPublish.CustomCss;
                contentToSave.UseCustomJs      = contentToPublish.UseCustomJs;
                contentToSave.CustomJs         = contentToPublish.CustomJs;
                contentToSave.EditInSourceMode = contentToPublish.EditInSourceMode;
            }

            UnitOfWork.BeginTransaction();
            pageContent.Content = contentService.SaveContentWithStatusUpdate(
                contentToSave,
                model.DesirableStatus);
            optionsService.SaveChildContentOptions(pageContent.Content, request.ChildContentOptionValues, model.DesirableStatus);

            if (pageContent.Content.ContentRegions != null &&
                pageContent.Content.ContentRegions.Count > 0)
            {
                if (!pageContent.Page.IsMasterPage)
                {
                    var logMessage = string.Format("Dynamic regions are not allowed. Page: {0}, Content: {1}", pageContent.Page, pageContent.Id);
                    throw new ValidationException(() => PagesGlobalization.SaveContent_DynamicRegionsAreNotAllowed_Message, logMessage);
                }
            }

            Repository.Save(pageContent);
            UnitOfWork.Commit();

            // Notify.
            if (model.DesirableStatus != ContentStatus.Preview)
            {
                if (isNew)
                {
                    Events.PageEvents.Instance.OnHtmlContentCreated((HtmlContent)pageContent.Content);
                    Events.PageEvents.Instance.OnPageContentInserted(pageContent);
                }
                else
                {
                    Events.PageEvents.Instance.OnHtmlContentUpdated((HtmlContent)pageContent.Content);
                }
            }

            return(new SavePageHtmlContentResponse {
                PageContentId = pageContent.Id,
                ContentId = pageContent.Content.Id,
                RegionId = pageContent.Region.Id,
                PageId = pageContent.Page.Id
            });
        }
Exemple #5
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>True if deleted successfully and False otherwise.</returns>
        public bool Execute(DeletePageContentCommandRequest request)
        {
            var deletingPageContent = Repository
                                      .AsQueryable <PageContent>()
                                      .Where(f => f.Id == request.PageContentId)
                                      .Fetch(f => f.Content)
                                      .Fetch(f => f.Page)
                                      .ThenFetchMany(f => f.PageContents)
                                      .ThenFetch(f => f.Content)
                                      .ToList()
                                      .FirstOne();

            if (request.ContentVersion != deletingPageContent.Content.Version)
            {
                throw new ConcurrentDataException(deletingPageContent.Content);
            }
            if (request.PageContentVersion != deletingPageContent.Version)
            {
                throw new ConcurrentDataException(deletingPageContent);
            }

            var htmlContainer = deletingPageContent.Content as IDynamicContentContainer;

            if (htmlContainer != null)
            {
                // Check if user has confirmed the deletion of content
                if (!request.IsUserConfirmed)
                {
                    var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(deletingPageContent.Page.Id, deletingPageContent.Content.Id);
                    if (hasAnyChildren)
                    {
                        var message    = PagesGlobalization.DeletePageContent_ContentHasChildrenContents_DeleteConfirmationMessage;
                        var logMessage = string.Format("User is trying to delete content which has children contents. Confirmation is required. PageContentId: {0}, ContentId: {1}, PageId: {2}",
                                                       request.PageContentId, deletingPageContent.Page.Id, deletingPageContent.Content.Id);
                        throw new ConfirmationRequestException(() => message, logMessage);
                    }
                }
            }

            var pageContentsToDelete = new List <PageContent> {
                deletingPageContent
            };

            pageContentsToDelete = RetrieveAllChildrenToDelete(deletingPageContent.Page.PageContents.ToList(), pageContentsToDelete, new[] { deletingPageContent.Id });

            UnitOfWork.BeginTransaction();

            var htmlContentsToDelete = new List <HtmlContent>();

            pageContentsToDelete.ForEach(pageContent =>
            {
                // If content is HTML content, delete HTML content
                var htmlContent = pageContent.Content as HtmlContent;
                if (htmlContent != null)
                {
                    var draft = pageContent.Content.History != null ? pageContent.Content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) : null;
                    if (draft != null)
                    {
                        Repository.Delete(draft);
                    }

                    Repository.Delete(pageContent.Content);
                    htmlContentsToDelete.Insert(0, htmlContent);
                }

                if (pageContent.Options != null)
                {
                    foreach (var option in pageContent.Options)
                    {
                        Repository.Delete(option);
                    }
                }

                Repository.Delete(pageContent);
            });

            UnitOfWork.Commit();

            // Notify
            pageContentsToDelete.Reverse();
            pageContentsToDelete.ForEach(pageContent => Events.PageEvents.Instance.OnPageContentDeleted(pageContent));
            htmlContentsToDelete.ForEach(htmlContent => Events.PageEvents.Instance.OnHtmlContentDeleted(htmlContent));

            return(true);
        }