diff --git a/notes/to-do.md b/notes/to-do.md index f4ec3ffe7..6ed7053fb 100644 --- a/notes/to-do.md +++ b/notes/to-do.md @@ -2,7 +2,6 @@ ## Miscellaneous -EF storage layer caching of post/page data recent posts viewcomponent for homepage @@ -10,10 +9,14 @@ Image Resizing and optimizing for uploaded images via: https://github.com/JimBobSquarePants/ImageProcessor http://jamessouth.me/archive/imageprocessor-core/ +ado sql storage + ## example project stuff -gulp/grunt work for production ie fontawesome copy to folder +using cloudscribe Core with NoDb + +using cloudscribe Core with EF latest trend single page site but the blog would be a separate page diff --git a/src/cloudscribe.Core.SimpleContent.Integration/Controllers/ContentSettingsController.cs b/src/cloudscribe.Core.SimpleContent.Integration/Controllers/ContentSettingsController.cs index 259e7cec9..f250f041c 100644 --- a/src/cloudscribe.Core.SimpleContent.Integration/Controllers/ContentSettingsController.cs +++ b/src/cloudscribe.Core.SimpleContent.Integration/Controllers/ContentSettingsController.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Author: Joe Audette // Created: 2016-08-07 -// Last Modified: 2016-08-14 +// Last Modified: 2016-09-12 // using cloudscribe.Core.Models; @@ -68,6 +68,7 @@ public async Task Index() model.PostsPerPage = projectSettings.PostsPerPage; model.BlogMenuLinksToNewestPost = projectSettings.BlogMenuLinksToNewestPost; model.DefaultPageSlug = projectSettings.DefaultPageSlug; + model.BlogPagePosition = projectSettings.BlogPagePosition; bool canManageUsers = false; try @@ -155,8 +156,13 @@ public async Task Index(ContentSettingsViewModel model) { needToClearMenuCache = true; } + if (projectSettings.BlogPagePosition != model.BlogPagePosition) + { + needToClearMenuCache = true; + } projectSettings.BlogMenuLinksToNewestPost = model.BlogMenuLinksToNewestPost; projectSettings.DefaultPageSlug = model.DefaultPageSlug; + projectSettings.BlogPagePosition = model.BlogPagePosition; await projectService.Update(projectSettings); if(needToClearMenuCache) diff --git a/src/cloudscribe.Core.SimpleContent.Integration/StartupExtenstions.cs b/src/cloudscribe.Core.SimpleContent.Integration/StartupExtenstions.cs index b55740228..60e9cc671 100644 --- a/src/cloudscribe.Core.SimpleContent.Integration/StartupExtenstions.cs +++ b/src/cloudscribe.Core.SimpleContent.Integration/StartupExtenstions.cs @@ -2,9 +2,14 @@ using cloudscribe.Core.SimpleContent.Integration.Controllers; using cloudscribe.SimpleContent.Models; using cloudscribe.SimpleContent.Web.TagHelpers; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.FileProviders; using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Logging; +using cloudscribe.Core.Models; +using Microsoft.AspNetCore.Http; namespace Microsoft.Extensions.DependencyInjection { @@ -41,7 +46,29 @@ public static RazorViewEngineOptions AddEmbeddedViewsForCloudscribeCoreSimpleCon return options; } - + public static AuthorizationOptions AddCloudscribeCoreSimpleContentIntegrationDefaultPolicies(this AuthorizationOptions options) + { + options.AddPolicy( + "BlogEditPolicy", + authBuilder => + { + //authBuilder.RequireClaim("blogId"); + authBuilder.RequireRole("Administrators"); + } + ); + + options.AddPolicy( + "PageEditPolicy", + authBuilder => + { + authBuilder.RequireRole("Administrators"); + }); + + return options; + } + + + } } diff --git a/src/cloudscribe.Core.SimpleContent.Integration/ViewModels/ContentSettingsViewModel.cs b/src/cloudscribe.Core.SimpleContent.Integration/ViewModels/ContentSettingsViewModel.cs index 5e0c976f2..5e2888615 100644 --- a/src/cloudscribe.Core.SimpleContent.Integration/ViewModels/ContentSettingsViewModel.cs +++ b/src/cloudscribe.Core.SimpleContent.Integration/ViewModels/ContentSettingsViewModel.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Author: Joe Audette // Created: 2016-08-05 -// Last Modified: 2016-08-15 +// Last Modified: 2016-09-12 // using cloudscribe.Core.Models; @@ -34,6 +34,8 @@ public ContentSettingsViewModel() public bool BlogMenuLinksToNewestPost { get; set; } = false; + public int BlogPagePosition { get; set; } = 2; // right after home page + //public string LocalMediaVirtualPath { get; set; } = "/media/images/"; diff --git a/src/cloudscribe.Core.SimpleContent.Integration/Views/ContentSettings/Index.cshtml b/src/cloudscribe.Core.SimpleContent.Integration/Views/ContentSettings/Index.cshtml index d0ff8032b..ab33f1050 100644 --- a/src/cloudscribe.Core.SimpleContent.Integration/Views/ContentSettings/Index.cshtml +++ b/src/cloudscribe.Core.SimpleContent.Integration/Views/ContentSettings/Index.cshtml @@ -17,10 +17,17 @@
- +
- - + + +
+
+
+ +
+ +
diff --git a/src/cloudscribe.Core.SimpleContent.Integration/project.json b/src/cloudscribe.Core.SimpleContent.Integration/project.json index 3d0bce6c7..7d8754626 100644 --- a/src/cloudscribe.Core.SimpleContent.Integration/project.json +++ b/src/cloudscribe.Core.SimpleContent.Integration/project.json @@ -16,17 +16,20 @@ "dependencies": { "cloudscribe.Core.Identity": "1.0.0-*", "cloudscribe.Core.Models": "1.0.2-*", + "cloudscribe.Core.Web": "1.0.0-*", "cloudscribe.SimpleContent.Models": "1.0.0-*", "cloudscribe.SimpleContent.Web": "1.0.0-*", "cloudscribe.Web.Common": "1.0.0-*", "cloudscribe.Web.Navigation": "1.0.2-*", "Microsoft.AspNetCore.Authorization": "1.0.0", "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0", + "Microsoft.AspNetCore.Http.Abstractions": "1.0.0", "Microsoft.AspNetCore.Mvc": "1.0.0-*", "Microsoft.AspNetCore.Mvc.Razor": "1.0.0-*", "Microsoft.AspNetCore.Routing": "1.0.0-*", "Microsoft.Extensions.FileProviders.Embedded": "1.0.0-*", "Microsoft.Extensions.Localization": "1.0.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0", "Microsoft.Extensions.Options": "1.0.0-*", "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0-*", "NETStandard.Library": "1.6.0-*" diff --git a/src/cloudscribe.SimpleContent.Storage.EFCore/Models/PageEntity.cs b/src/cloudscribe.SimpleContent.Storage.EFCore/Models/PageEntity.cs index 81cc594a8..981e804e5 100644 --- a/src/cloudscribe.SimpleContent.Storage.EFCore/Models/PageEntity.cs +++ b/src/cloudscribe.SimpleContent.Storage.EFCore/Models/PageEntity.cs @@ -61,7 +61,6 @@ public List Categories { get { - //if(categories.Count == 0) var list = CategoriesCsv.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(c => c.Trim().ToLower()).ToList(); @@ -111,7 +110,6 @@ public List PageComments set { pageComments = value; } } - public static PageEntity FromIPage(IPage page) { var p = new PageEntity(); diff --git a/src/cloudscribe.SimpleContent.Storage.EFCore/PostQueries.cs b/src/cloudscribe.SimpleContent.Storage.EFCore/PostQueries.cs index d7c018508..83b4345cb 100644 --- a/src/cloudscribe.SimpleContent.Storage.EFCore/PostQueries.cs +++ b/src/cloudscribe.SimpleContent.Storage.EFCore/PostQueries.cs @@ -81,7 +81,6 @@ public async Task GetPosts( .OrderByDescending(x => x.PubDate) ; - var posts = await query .AsNoTracking() .Skip(offset) @@ -97,52 +96,6 @@ public async Task GetPosts( return result; } - //private async Task> GetCommentsForPageOfPosts( - // string blogId, - // string category, - // bool includeUnpublished, - // DateTime currentTime, - // int pageNumber, - // int pageSize, - // CancellationToken cancellationToken = default(CancellationToken) - // ) - //{ - // ThrowIfDisposed(); - // cancellationToken.ThrowIfCancellationRequested(); - - // int offset = (pageSize * pageNumber) - pageSize; - - - // var result = new List(); - - // var query = from c in dbContext.Comments - // join x in dbContext.Posts - // on c.ContentId equals x.Id - // orderby x.PubDate - // where ( - // x.BlogId == blogId - // && (includeUnpublished || (x.IsPublished && x.PubDate <= currentTime)) - // && (string.IsNullOrEmpty(category) || (EF.Property(x, "CategoryCsv").Contains(category))) // will this work? - // ) - - // select c - - // ; - - - // //List posts = await query - // // .AsNoTracking() - // // .Skip(offset) - // // .Take(pageSize) - // // .ToListAsync(cancellationToken) - // // .ConfigureAwait(false); - - - - - // return result; - //} - public async Task GetCount( string blogId, string category, @@ -403,16 +356,6 @@ public async Task> GetCategories( var result = new Dictionary(); - //var query = dbContext.PostCategories - // .AsNoTracking() - // .Where(t => t.ProjectId == blogId) - // .Select(x => new - // { - // cat = x.Value, - // count = dbContext.PostCategories.Count(u => u.ProjectId == x.ProjectId && u.Value == x.Value ) - // }) - // ; - var query = from x in dbContext.PostCategories join y in dbContext.Posts on x.PostEntityId equals y.Id @@ -420,11 +363,6 @@ on x.PostEntityId equals y.Id (x.ProjectId.Equals(blogId)) && (includeUnpublished || (y.IsPublished && y.PubDate <= DateTime.UtcNow)) ) - //select new - //{ - // cat = x.Value, - // count = dbContext.PostCategories.Count(u => u.ProjectId == x.ProjectId && u.Value == x.Value ) - //} select x ; diff --git a/src/cloudscribe.SimpleContent.Web/Controllers/PageController.cs b/src/cloudscribe.SimpleContent.Web/Controllers/PageController.cs index 73b678581..6dddaa7fa 100644 --- a/src/cloudscribe.SimpleContent.Web/Controllers/PageController.cs +++ b/src/cloudscribe.SimpleContent.Web/Controllers/PageController.cs @@ -231,7 +231,7 @@ public async Task AjaxPost(PageEditViewModel model) page.MetaDescription = model.MetaDescription; page.Content = model.Content; if (page.PageOrder != model.PageOrder) needToClearCache = true; - //post.Categories = categories.ToList(); + } else { diff --git a/src/cloudscribe.SimpleContent.Web/Services/PagesNavigationTreeBuilder.cs b/src/cloudscribe.SimpleContent.Web/Services/PagesNavigationTreeBuilder.cs index 9a2091f9e..6e19edd53 100644 --- a/src/cloudscribe.SimpleContent.Web/Services/PagesNavigationTreeBuilder.cs +++ b/src/cloudscribe.SimpleContent.Web/Services/PagesNavigationTreeBuilder.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Author: Joe Audette // Created: 2016-05-27 -// Last Modified: 2016-09-08 +// Last Modified: 2016-09-12 // using cloudscribe.SimpleContent.Models; @@ -104,8 +104,14 @@ private async Task> BuildTreeInternal(NavigationTreeBui var treeRoot = new TreeNode(rootNav); var rootList = await pageService.GetRootPages().ConfigureAwait(false); + var rootListCount = rootList.Count(); + var blogPosition = project.BlogPagePosition; + if (project.AddBlogToPagesTree) + { + if (blogPosition > rootListCount) blogPosition = rootListCount; + } - if(rootList.Count() <= 1) + if (rootListCount <= 1) { // if there are no pages we won't hit the loop below so go ahead and add the blog page if (project.AddBlogToPagesTree) { @@ -138,7 +144,7 @@ private async Task> BuildTreeInternal(NavigationTreeBui foreach (var page in rootList) { var node = new NavigationNode(); - if (project.AddBlogToPagesTree && rootPosition == project.BlogPagePosition) + if (project.AddBlogToPagesTree && rootPosition == blogPosition) { node.Key = project.BlogPageText; node.ParentKey = "RootNode"; diff --git a/src/example.WebApp/Startup.cs b/src/example.WebApp/Startup.cs index bf00afbbb..2ca986f6d 100644 --- a/src/example.WebApp/Startup.cs +++ b/src/example.WebApp/Startup.cs @@ -81,29 +81,23 @@ public void ConfigureServices(IServiceCollection services) ConfigureDataStorage(services); - //services.AddCloudscribeCoreNoDbStorage(); - //services.AddCloudscribeLoggingNoDbStorage(Configuration); + services.AddCloudscribeLogging(); services.AddScoped(); - // + services.AddScoped(); services.AddScoped(); services.AddCloudscribeCore(Configuration); services.AddCloudscribeIdentity(); - - //services.AddNoDbStorageForSimpleContent(); - + services.Configure>(Configuration.GetSection("ContentProjects")); services.AddScoped(); services.AddScoped(); - //services.Configure>(Configuration.GetSection("ClaimMaps")); - //services.AddScoped(); - - + services.AddCloudscribeCoreIntegrationForSimpleContent(); services.AddSimpleContent(Configuration); @@ -234,41 +228,12 @@ cloudscribe.Logging.Web.ILogRepository logRepo && multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName && tenant.SiteFolderName.Length > 0; - var externalCookieOptions = SetupOtherCookies( - cloudscribe.Core.Identity.AuthenticationScheme.External, - multiTenantOptions.UseRelatedSitesMode, - tenant); - builder.UseCookieAuthentication(externalCookieOptions); - - var twoFactorRememberMeCookieOptions = SetupOtherCookies( - cloudscribe.Core.Identity.AuthenticationScheme.TwoFactorRememberMe, - multiTenantOptions.UseRelatedSitesMode, - tenant); - builder.UseCookieAuthentication(twoFactorRememberMeCookieOptions); - - var twoFactorUserIdCookie = SetupOtherCookies( - cloudscribe.Core.Identity.AuthenticationScheme.TwoFactorUserId, + builder.UseCloudscribeCoreDefaultAuthentication( + loggerFactory, multiTenantOptions.UseRelatedSitesMode, + shouldUseFolder, tenant); - builder.UseCookieAuthentication(twoFactorUserIdCookie); - - var cookieEvents = new CookieAuthenticationEvents(); - var logger = loggerFactory.CreateLogger(); - var cookieValidator = new cloudscribe.Core.Identity.SiteAuthCookieValidator(logger); - var appCookieOptions = SetupAppCookie( - cookieEvents, - cookieValidator, - cloudscribe.Core.Identity.AuthenticationScheme.Application, - multiTenantOptions.UseRelatedSitesMode, - tenant - ); - builder.UseCookieAuthentication(appCookieOptions); - - // known issue here is if a site is updated to populate the - // social auth keys, it currently requires a restart so that the middleware gets registered - // in order for it to work or for the social auth buttons to appear - builder.UseSocialAuth(ctx.Tenant, externalCookieOptions, shouldUseFolder); - + }); UseMvc(app, multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName); @@ -375,64 +340,28 @@ private void ConfigureAuthPolicy(IServiceCollection services) services.AddAuthorization(options => { - options.AddPolicy( - "ServerAdminPolicy", - authBuilder => - { - authBuilder.RequireRole("ServerAdmins"); - }); - - options.AddPolicy( - "CoreDataPolicy", - authBuilder => - { - authBuilder.RequireRole("ServerAdmins"); - }); - - options.AddPolicy( - "AdminPolicy", - authBuilder => - { - authBuilder.RequireRole("ServerAdmins", "Administrators"); - }); - - options.AddPolicy( - "UserManagementPolicy", - authBuilder => - { - authBuilder.RequireRole("ServerAdmins", "Administrators"); - }); - - options.AddPolicy( - "RoleAdminPolicy", - authBuilder => - { - authBuilder.RequireRole("Role Administrators", "Administrators"); - }); - - options.AddPolicy( - "SystemLogPolicy", - authBuilder => - { - authBuilder.RequireRole("ServerAdmins"); - }); - - - options.AddPolicy( - "BlogEditPolicy", - authBuilder => - { - //authBuilder.RequireClaim("blogId"); - authBuilder.RequireRole("Administrators"); - } - ); - - options.AddPolicy( - "PageEditPolicy", - authBuilder => - { - authBuilder.RequireRole("Administrators"); - }); + options.AddCloudscribeCoreDefaultPolicies(); + + options.AddCloudscribeLoggingDefaultPolicy(); + + options.AddCloudscribeCoreSimpleContentIntegrationDefaultPolicies(); + + // this is what the above extension adds + //options.AddPolicy( + // "BlogEditPolicy", + // authBuilder => + // { + // //authBuilder.RequireClaim("blogId"); + // authBuilder.RequireRole("Administrators"); + // } + // ); + + //options.AddPolicy( + // "PageEditPolicy", + // authBuilder => + // { + // authBuilder.RequireRole("Administrators"); + // }); // add other policies here @@ -484,71 +413,5 @@ IServiceProvider serviceProvider } - - private CookieAuthenticationOptions SetupAppCookie( - CookieAuthenticationEvents cookieEvents, - cloudscribe.Core.Identity.SiteAuthCookieValidator siteValidator, - string scheme, - bool useRelatedSitesMode, - cloudscribe.Core.Models.SiteSettings tenant - ) - { - var options = new CookieAuthenticationOptions(); - if (useRelatedSitesMode) - { - options.AuthenticationScheme = scheme; - options.CookieName = scheme; - options.CookiePath = "/"; - } - else - { - options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}"; - options.CookieName = $"{scheme}-{tenant.SiteFolderName}"; - options.CookiePath = "/" + tenant.SiteFolderName; - cookieEvents.OnValidatePrincipal = siteValidator.ValidatePrincipal; - } - - var tenantPathBase = string.IsNullOrEmpty(tenant.SiteFolderName) - ? PathString.Empty - : new PathString("/" + tenant.SiteFolderName); - - options.LoginPath = tenantPathBase + "/account/login"; - options.LogoutPath = tenantPathBase + "/account/logoff"; - options.AccessDeniedPath = tenantPathBase + "/account/accessdenied"; - - options.Events = cookieEvents; - - options.AutomaticAuthenticate = true; - options.AutomaticChallenge = false; - - - return options; - } - - private CookieAuthenticationOptions SetupOtherCookies( - string scheme, - bool useRelatedSitesMode, - cloudscribe.Core.Models.SiteSettings tenant - ) - { - var options = new CookieAuthenticationOptions(); - if (useRelatedSitesMode) - { - options.AuthenticationScheme = scheme; - options.CookieName = scheme; - options.CookiePath = "/"; - } - else - { - options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}"; - options.CookieName = $"{scheme}-{tenant.SiteFolderName}"; - options.CookiePath = "/" + tenant.SiteFolderName; - } - - options.AutomaticAuthenticate = false; - - return options; - - } } }