public DbSetup( cloudscribe.DbHelpers.SQLite.SqliteConnectionstringResolver connectionStringResolver, ILogger<DbSetup> logger, IVersionProviderFactory versionProviderFactory) { if (connectionStringResolver == null) { throw new ArgumentNullException(nameof(connectionStringResolver)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (versionProviderFactory == null) { throw new ArgumentNullException(nameof(versionProviderFactory)); } versionProviders = versionProviderFactory; log = logger; connectionString = connectionStringResolver.Resolve(); sqliteFilePath = connectionStringResolver.SqliteFilePath; // possibly will change this later to have SqliteFactory/DbProviderFactory injected AdoHelper = new AdoHelper(SqliteFactory.Instance); }
private void ConfigureLogging( ILoggerFactory loggerFactory, IServiceProvider serviceProvider , cloudscribe.Logging.Web.ILogRepository logRepo ) { // a customizable filter for logging LogLevel minimumLevel = LogLevel.Information; // add exclusions to remove noise in the logs var excludedLoggers = new List<string> { "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware", "Microsoft.AspNetCore.Hosting.Internal.WebHost", }; Func<string, LogLevel, bool> logFilter = (string loggerName, LogLevel logLevel) => { if (logLevel < minimumLevel) { return false; } if (excludedLoggers.Contains(loggerName)) { return false; } return true; }; loggerFactory.AddDbLogger(serviceProvider, logFilter, logRepo); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // you can add things to this method signature and they will be injected as long as they were registered during // ConfigureServices public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<cloudscribe.Core.Models.MultiTenantOptions> multiTenantOptionsAccessor, IServiceProvider serviceProvider, IOptions<RequestLocalizationOptions> localizationOptionsAccessor ,cloudscribe.Logging.Web.ILogRepository logRepo ) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); ConfigureLogging(loggerFactory, serviceProvider, logRepo); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink(); } var storage = Configuration["DevOptions:DbPlatform"]; switch (storage) { case "NoDb": CoreNoDbStartup.InitializeDataAsync(app.ApplicationServices).Wait(); // you can use this hack to add clients and scopes into the db since // there is currently no ui to do it // you should not use this on the first run that actually creates the initial cloudscribe data // you must wait until after that and then you can get the needed siteid from the database // this will only run at startup time and only add data if no data exists for the given site. // if you pass in an invalid siteid it will not fail, you will get data with a bad siteid // make note of your siteid, don't use these, these are from my NoDb storage // site1 05301194-da1d-43a8-9aa4-6c5f8959f37b // site2 a9e2c249-90b4-4770-9e99-9702d89f73b6 // replace null with your siteid and run the app, then change it back to null since it can only be a one time task string sId = null; CloudscribeIdentityServerIntegrationNoDbStorage.InitializeDatabaseAsync( app.ApplicationServices, sId, GetClients(), GetScopes() ).Wait(); break; case "ef": default: // this creates ensures the database is created and initial data CoreEFStartup.InitializeDatabaseAsync(app.ApplicationServices).Wait(); // this one is only needed if using cloudscribe Logging with EF as the logging storage LoggingEFStartup.InitializeDatabaseAsync(app.ApplicationServices).Wait(); // you can use this hack to add clients and scopes into the db since // there is currently no ui to do it // you should not use this on the first run that actually creates the initial cloudscribe data // you must wait until after that and then you can get the needed siteid from the database // this will only run at startup time and only add data if no data exists for the given site. // if you pass in an invalid siteid it will not fail, you will get data with a bad siteid // make note of your siteid, don't use these, these are from my db // site1 8f54733c-3f3a-4971-bb1f-8950cea42f1a // site2 7c111db3-e270-497a-9a12-aed436c764c6 // replace null with your siteid and run the app, then change it back to null since it can only be a one time task string siteId = null; CloudscribeIdentityServerIntegrationEFCoreStorage.InitializeDatabaseAsync( app.ApplicationServices, siteId, GetClients(), GetScopes() ).Wait(); break; } app.UseForwardedHeaders(); app.UseStaticFiles(); app.UseSession(); app.UseRequestLocalization(localizationOptionsAccessor.Value); app.UseMultitenancy<cloudscribe.Core.Models.SiteContext>(); var multiTenantOptions = multiTenantOptionsAccessor.Value; app.UsePerTenant<cloudscribe.Core.Models.SiteContext>((ctx, builder) => { // custom 404 and error page - this preserves the status code (ie 404) if(string.IsNullOrEmpty(ctx.Tenant.SiteFolderName)) { builder.UseStatusCodePagesWithReExecute("/Home/Error/{0}"); } else { builder.UseStatusCodePagesWithReExecute("/" + ctx.Tenant.SiteFolderName + "/Home/Error/{0}"); } builder.UseCloudscribeCoreDefaultAuthentication( loggerFactory, multiTenantOptions, ctx.Tenant); // to make this multi tenant for folders // using a fork of IdentityServer4 and hoping to get changes so we don't need a fork // https://github.com/IdentityServer/IdentityServer4/issues/19 builder.UseIdentityServer(); // this sets up the authentication for apis within this application endpoint // ie apis that are hosted in the same web app endpoint with the authority server // this is not needed here if you are only using separate api endpoints // it is needed in the startup of those separate endpoints builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions { Authority = "https://localhost:44399", // using the site aliasid as the scope so each tenant has a different scope // you can view the aliasid from site settings // clients must be configured with the scope to have access to the apis for the tenant ScopeName = ctx.Tenant.AliasId, RequireHttpsMetadata = true }); }); UseMvc(app, multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName); }
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; } return options; }
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.Events = cookieEvents; options.AutomaticAuthenticate = true; options.AutomaticChallenge = true; return options; }