Merge pull request #1245 from hishamco/clean-startup
Clean Startup Class
This commit is contained in:
		| @ -1,3 +1,5 @@ | ||||
| using Microsoft.Extensions.Localization; | ||||
| using System.Runtime.CompilerServices; | ||||
| using Microsoft.Extensions.Localization; | ||||
|  | ||||
| [assembly: RootNamespace("Oqtane")] | ||||
| [assembly: InternalsVisibleTo("Oqtane.Server")] | ||||
|  | ||||
| @ -0,0 +1,54 @@ | ||||
| using Microsoft.AspNetCore.Components.Authorization; | ||||
| using Oqtane.Providers; | ||||
| using Oqtane.Services; | ||||
| using Oqtane.Shared; | ||||
|  | ||||
| namespace Microsoft.Extensions.DependencyInjection | ||||
| { | ||||
|     public static class OqtaneServiceCollectionExtensions | ||||
|     { | ||||
|         public static IServiceCollection AddOqtaneAuthorization(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddAuthorizationCore(); | ||||
|             services.AddScoped<IdentityAuthenticationStateProvider>(); | ||||
|             services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<IdentityAuthenticationStateProvider>()); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         internal static IServiceCollection AddOqtaneScopedServices(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddScoped<SiteState>(); | ||||
|             services.AddScoped<IInstallationService, InstallationService>(); | ||||
|             services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>(); | ||||
|             services.AddScoped<IThemeService, ThemeService>(); | ||||
|             services.AddScoped<IAliasService, AliasService>(); | ||||
|             services.AddScoped<ITenantService, TenantService>(); | ||||
|             services.AddScoped<ISiteService, SiteService>(); | ||||
|             services.AddScoped<IPageService, PageService>(); | ||||
|             services.AddScoped<IModuleService, ModuleService>(); | ||||
|             services.AddScoped<IPageModuleService, PageModuleService>(); | ||||
|             services.AddScoped<IUserService, UserService>(); | ||||
|             services.AddScoped<IProfileService, ProfileService>(); | ||||
|             services.AddScoped<IRoleService, RoleService>(); | ||||
|             services.AddScoped<IUserRoleService, UserRoleService>(); | ||||
|             services.AddScoped<ISettingService, SettingService>(); | ||||
|             services.AddScoped<IPackageService, PackageService>(); | ||||
|             services.AddScoped<ILogService, LogService>(); | ||||
|             services.AddScoped<IJobService, JobService>(); | ||||
|             services.AddScoped<IJobLogService, JobLogService>(); | ||||
|             services.AddScoped<INotificationService, NotificationService>(); | ||||
|             services.AddScoped<IFolderService, FolderService>(); | ||||
|             services.AddScoped<IFileService, FileService>(); | ||||
|             services.AddScoped<ISiteTemplateService, SiteTemplateService>(); | ||||
|             services.AddScoped<ISqlService, SqlService>(); | ||||
|             services.AddScoped<ISystemService, SystemService>(); | ||||
|             services.AddScoped<ILocalizationService, LocalizationService>(); | ||||
|             services.AddScoped<ILanguageService, LanguageService>(); | ||||
|             services.AddScoped<IDatabaseService, DatabaseService>(); | ||||
|             services.AddScoped<ISyncService, SyncService>(); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -8,13 +8,11 @@ using System.Net.Http; | ||||
| using System.Reflection; | ||||
| using System.Runtime.Loader; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Components.Authorization; | ||||
| using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||||
| using Microsoft.AspNetCore.Localization; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.JSInterop; | ||||
| using Oqtane.Modules; | ||||
| using Oqtane.Providers; | ||||
| using Oqtane.Services; | ||||
| using Oqtane.Shared; | ||||
| using Oqtane.UI; | ||||
| @ -27,7 +25,8 @@ namespace Oqtane.Client | ||||
|         { | ||||
|             var builder = WebAssemblyHostBuilder.CreateDefault(args); | ||||
|             builder.RootComponents.Add<App>("app"); | ||||
|             HttpClient httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)}; | ||||
|  | ||||
|             var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)}; | ||||
|  | ||||
|             builder.Services.AddSingleton(httpClient); | ||||
|             builder.Services.AddOptions(); | ||||
| @ -36,40 +35,10 @@ namespace Oqtane.Client | ||||
|             builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); | ||||
|  | ||||
|             // register auth services | ||||
|             builder.Services.AddAuthorizationCore(); | ||||
|             builder.Services.AddScoped<IdentityAuthenticationStateProvider>(); | ||||
|             builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<IdentityAuthenticationStateProvider>()); | ||||
|             builder.Services.AddOqtaneAuthorization(); | ||||
|  | ||||
|             // register scoped core services | ||||
|             builder.Services.AddScoped<SiteState>(); | ||||
|             builder.Services.AddScoped<IInstallationService, InstallationService>(); | ||||
|             builder.Services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>(); | ||||
|             builder.Services.AddScoped<IThemeService, ThemeService>(); | ||||
|             builder.Services.AddScoped<IAliasService, AliasService>(); | ||||
|             builder.Services.AddScoped<ITenantService, TenantService>(); | ||||
|             builder.Services.AddScoped<ISiteService, SiteService>(); | ||||
|             builder.Services.AddScoped<IPageService, PageService>(); | ||||
|             builder.Services.AddScoped<IModuleService, ModuleService>(); | ||||
|             builder.Services.AddScoped<IPageModuleService, PageModuleService>(); | ||||
|             builder.Services.AddScoped<IUserService, UserService>(); | ||||
|             builder.Services.AddScoped<IProfileService, ProfileService>(); | ||||
|             builder.Services.AddScoped<IRoleService, RoleService>(); | ||||
|             builder.Services.AddScoped<IUserRoleService, UserRoleService>(); | ||||
|             builder.Services.AddScoped<ISettingService, SettingService>(); | ||||
|             builder.Services.AddScoped<IPackageService, PackageService>(); | ||||
|             builder.Services.AddScoped<ILogService, LogService>(); | ||||
|             builder.Services.AddScoped<IJobService, JobService>(); | ||||
|             builder.Services.AddScoped<IJobLogService, JobLogService>(); | ||||
|             builder.Services.AddScoped<INotificationService, NotificationService>(); | ||||
|             builder.Services.AddScoped<IFolderService, FolderService>(); | ||||
|             builder.Services.AddScoped<IFileService, FileService>(); | ||||
|             builder.Services.AddScoped<ISiteTemplateService, SiteTemplateService>(); | ||||
|             builder.Services.AddScoped<ISqlService, SqlService>(); | ||||
|             builder.Services.AddScoped<ISystemService, SystemService>(); | ||||
|             builder.Services.AddScoped<ILocalizationService, LocalizationService>(); | ||||
|             builder.Services.AddScoped<ILanguageService, LanguageService>(); | ||||
|             builder.Services.AddScoped<IDatabaseService, DatabaseService>(); | ||||
|             builder.Services.AddScoped<ISyncService, SyncService>(); | ||||
|             builder.Services.AddOqtaneScopedServices(); | ||||
|  | ||||
|             await LoadClientAssemblies(httpClient); | ||||
|  | ||||
| @ -77,38 +46,15 @@ namespace Oqtane.Client | ||||
|             foreach (var assembly in assemblies) | ||||
|             { | ||||
|                 // dynamically register module services | ||||
|                 var implementationTypes = assembly.GetInterfaces<IService>(); | ||||
|                 foreach (var implementationType in implementationTypes) | ||||
|                 { | ||||
|                     if (implementationType.AssemblyQualifiedName != null) | ||||
|                     { | ||||
|                         var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}")); | ||||
|                         builder.Services.AddScoped(serviceType ?? implementationType, implementationType); | ||||
|                     } | ||||
|                 } | ||||
|                 RegisterModuleServices(assembly, builder.Services); | ||||
|  | ||||
|                 // register client startup services | ||||
|                 var startUps = assembly.GetInstances<IClientStartup>(); | ||||
|                 foreach (var startup in startUps) | ||||
|                 { | ||||
|                     startup.ConfigureServices(builder.Services); | ||||
|                 } | ||||
|                 RegisterClientStartups(assembly, builder.Services); | ||||
|             } | ||||
|  | ||||
|             var host = builder.Build(); | ||||
|             var jsRuntime = host.Services.GetRequiredService<IJSRuntime>(); | ||||
|             var interop = new Interop(jsRuntime); | ||||
|             var localizationCookie = await interop.GetCookie(CookieRequestCultureProvider.DefaultCookieName); | ||||
|             var culture = CookieRequestCultureProvider.ParseCookieValue(localizationCookie).UICultures[0].Value; | ||||
|             var localizationService = host.Services.GetRequiredService<ILocalizationService>(); | ||||
|             var cultures = await localizationService.GetCulturesAsync(); | ||||
|  | ||||
|             if (culture == null || !cultures.Any(c => c.Name.Equals(culture, StringComparison.OrdinalIgnoreCase))) | ||||
|             { | ||||
|                 culture = cultures.Single(c => c.IsDefault).Name; | ||||
|             } | ||||
|  | ||||
|             SetCulture(culture); | ||||
|             await SetCultureFromLocalizationCookie(host.Services); | ||||
|  | ||||
|             ServiceActivator.Configure(host.Services); | ||||
|  | ||||
| @ -164,6 +110,45 @@ namespace Oqtane.Client | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static void RegisterModuleServices(Assembly assembly, IServiceCollection services) | ||||
|         { | ||||
|             var implementationTypes = assembly.GetInterfaces<IService>(); | ||||
|             foreach (var implementationType in implementationTypes) | ||||
|             { | ||||
|                 if (implementationType.AssemblyQualifiedName != null) | ||||
|                 { | ||||
|                     var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}")); | ||||
|                     services.AddScoped(serviceType ?? implementationType, implementationType); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static void RegisterClientStartups(Assembly assembly, IServiceCollection services) | ||||
|         { | ||||
|             var startUps = assembly.GetInstances<IClientStartup>(); | ||||
|             foreach (var startup in startUps) | ||||
|             { | ||||
|                 startup.ConfigureServices(services); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static async Task SetCultureFromLocalizationCookie(IServiceProvider serviceProvider) | ||||
|         { | ||||
|             var jsRuntime = serviceProvider.GetRequiredService<IJSRuntime>(); | ||||
|             var interop = new Interop(jsRuntime); | ||||
|             var localizationCookie = await interop.GetCookie(CookieRequestCultureProvider.DefaultCookieName); | ||||
|             var culture = CookieRequestCultureProvider.ParseCookieValue(localizationCookie).UICultures[0].Value; | ||||
|             var localizationService = serviceProvider.GetRequiredService<ILocalizationService>(); | ||||
|             var cultures = await localizationService.GetCulturesAsync(); | ||||
|  | ||||
|             if (culture == null || !cultures.Any(c => c.Name.Equals(culture, StringComparison.OrdinalIgnoreCase))) | ||||
|             { | ||||
|                 culture = cultures.Single(c => c.IsDefault).Name; | ||||
|             } | ||||
|  | ||||
|             SetCulture(culture); | ||||
|         } | ||||
|  | ||||
|         private static void SetCulture(string culture) | ||||
|         { | ||||
|             var cultureInfo = CultureInfo.GetCultureInfo(culture); | ||||
|  | ||||
| @ -1,16 +1,25 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Net; | ||||
| using System.Net.Http; | ||||
| using System.Reflection; | ||||
| using System.Runtime.Loader; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Components; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.OpenApi.Models; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Interfaces; | ||||
| using Oqtane.Modules; | ||||
| using Oqtane.Repository; | ||||
| using Oqtane.Security; | ||||
| using Oqtane.Services; | ||||
| using Oqtane.Shared; | ||||
|  | ||||
| // ReSharper disable once CheckNamespace | ||||
| namespace Microsoft.Extensions.DependencyInjection | ||||
| { | ||||
|     public static class OqtaneServiceCollectionExtensions | ||||
| @ -24,6 +33,160 @@ namespace Microsoft.Extensions.DependencyInjection | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         public static IServiceCollection AddOqtaneDbContext(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddDbContext<MasterDBContext>(options => { }); | ||||
|             services.AddDbContext<TenantDBContext>(options => { }); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         public static IServiceCollection AddOqtaneAuthorizationPolicies(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddAuthorizationCore(options => | ||||
|             { | ||||
|                 options.AddPolicy(PolicyNames.ViewPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ViewModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ViewFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ListFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse))); | ||||
|             }); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         internal static IServiceCollection AddOqtaneSingletonServices(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddSingleton<IInstallationManager, InstallationManager>(); | ||||
|             services.AddSingleton<ISyncManager, SyncManager>(); | ||||
|             services.AddSingleton<IDatabaseManager, DatabaseManager>(); | ||||
|             services.AddSingleton<IConfigManager, ConfigManager>(); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         internal static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>(); | ||||
|             services.AddTransient<IThemeRepository, ThemeRepository>(); | ||||
|             services.AddTransient<IUserPermissions, UserPermissions>(); | ||||
|             services.AddTransient<ITenantResolver, TenantResolver>(); | ||||
|             services.AddTransient<IAliasRepository, AliasRepository>(); | ||||
|             services.AddTransient<ITenantRepository, TenantRepository>(); | ||||
|             services.AddTransient<ISiteRepository, SiteRepository>(); | ||||
|             services.AddTransient<IPageRepository, PageRepository>(); | ||||
|             services.AddTransient<IModuleRepository, ModuleRepository>(); | ||||
|             services.AddTransient<IPageModuleRepository, PageModuleRepository>(); | ||||
|             services.AddTransient<IUserRepository, UserRepository>(); | ||||
|             services.AddTransient<IProfileRepository, ProfileRepository>(); | ||||
|             services.AddTransient<IRoleRepository, RoleRepository>(); | ||||
|             services.AddTransient<IUserRoleRepository, UserRoleRepository>(); | ||||
|             services.AddTransient<IPermissionRepository, PermissionRepository>(); | ||||
|             services.AddTransient<ISettingRepository, SettingRepository>(); | ||||
|             services.AddTransient<ILogRepository, LogRepository>(); | ||||
|             services.AddTransient<ILogManager, LogManager>(); | ||||
|             services.AddTransient<ILocalizationManager, LocalizationManager>(); | ||||
|             services.AddTransient<IJobRepository, JobRepository>(); | ||||
|             services.AddTransient<IJobLogRepository, JobLogRepository>(); | ||||
|             services.AddTransient<INotificationRepository, NotificationRepository>(); | ||||
|             services.AddTransient<IFolderRepository, FolderRepository>(); | ||||
|             services.AddTransient<IFileRepository, FileRepository>(); | ||||
|             services.AddTransient<ISiteTemplateRepository, SiteTemplateRepository>(); | ||||
|             services.AddTransient<ISqlRepository, SqlRepository>(); | ||||
|             services.AddTransient<IUpgradeManager, UpgradeManager>(); | ||||
|             services.AddTransient<ILanguageRepository, LanguageRepository>(); | ||||
|             // obsolete - replaced by ITenantManager | ||||
|             services.AddTransient<ITenantResolver, TenantResolver>(); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         public static IServiceCollection ConfigureOqtaneCookieOptions(this IServiceCollection services) | ||||
|         { | ||||
|             services.ConfigureApplicationCookie(options => | ||||
|             { | ||||
|                 options.Cookie.HttpOnly = false; | ||||
|                 options.Cookie.SameSite = SameSiteMode.Strict; | ||||
|                 options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; | ||||
|                 options.Events.OnRedirectToLogin = context => | ||||
|                 { | ||||
|                     context.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                     return Task.CompletedTask; | ||||
|                 }; | ||||
|                 options.Events.OnRedirectToAccessDenied = context => | ||||
|                 { | ||||
|                     context.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                     return Task.CompletedTask; | ||||
|                 }; | ||||
|                 options.Events.OnValidatePrincipal = PrincipalValidator.ValidateAsync; | ||||
|             }); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         public static IServiceCollection ConfigureOqtaneIdentityOptions(this IServiceCollection services) | ||||
|         { | ||||
|             services.Configure<IdentityOptions>(options => | ||||
|             { | ||||
|                 // Password settings | ||||
|                 options.Password.RequireDigit = false; | ||||
|                 options.Password.RequiredLength = 6; | ||||
|                 options.Password.RequireNonAlphanumeric = false; | ||||
|                 options.Password.RequireUppercase = false; | ||||
|                 options.Password.RequireLowercase = false; | ||||
|  | ||||
|                 // Lockout settings | ||||
|                 options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); | ||||
|                 options.Lockout.MaxFailedAccessAttempts = 10; | ||||
|                 options.Lockout.AllowedForNewUsers = true; | ||||
|  | ||||
|                 // User settings | ||||
|                 options.User.RequireUniqueEmail = false; | ||||
|             }); | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         internal static IServiceCollection TryAddHttpClientWithAuthenticationCookie(this IServiceCollection services) | ||||
|         { | ||||
|             if (!services.Any(x => x.ServiceType == typeof(HttpClient))) | ||||
|             { | ||||
|                 services.AddScoped(s => | ||||
|                 { | ||||
|                     // creating the URI helper needs to wait until the JS Runtime is initialized, so defer it. | ||||
|                     var navigationManager = s.GetRequiredService<NavigationManager>(); | ||||
|                     var httpContextAccessor = s.GetRequiredService<IHttpContextAccessor>(); | ||||
|                     var authToken = httpContextAccessor.HttpContext.Request.Cookies[".AspNetCore.Identity.Application"]; | ||||
|                     var client = new HttpClient(new HttpClientHandler { UseCookies = false }); | ||||
|                     if (authToken != null) | ||||
|                     { | ||||
|                         client.DefaultRequestHeaders.Add("Cookie", ".AspNetCore.Identity.Application=" + authToken); | ||||
|                     } | ||||
|  | ||||
|                     client.BaseAddress = new Uri(navigationManager.Uri); | ||||
|  | ||||
|                     return client; | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         internal static IServiceCollection TryAddSwagger(this IServiceCollection services, bool useSwagger) | ||||
|         { | ||||
|             if (useSwagger) | ||||
|             { | ||||
|                 services.AddSwaggerGen(c => | ||||
|                 { | ||||
|                     c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" }); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|  | ||||
|         private static IServiceCollection AddOqtaneServices(this IServiceCollection services, Runtime runtime) | ||||
|         { | ||||
|             if (services is null) | ||||
|  | ||||
| @ -1,36 +1,29 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Net; | ||||
| using System.Net.Http; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| using Microsoft.AspNetCore.Components; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.OpenApi.Models; | ||||
| using Oqtane.Extensions; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Repository; | ||||
| using Oqtane.Security; | ||||
| using Oqtane.Services; | ||||
| using Oqtane.Shared; | ||||
|  | ||||
| namespace Oqtane | ||||
| { | ||||
|     public class Startup | ||||
|     { | ||||
|         private Runtime _runtime; | ||||
|         private bool _useSwagger; | ||||
|         private IWebHostEnvironment _env; | ||||
|         private string[] _supportedCultures; | ||||
|         private readonly Runtime _runtime; | ||||
|         private readonly bool _useSwagger; | ||||
|         private readonly IWebHostEnvironment _env; | ||||
|         private readonly string[] _supportedCultures; | ||||
|  | ||||
|         public IConfigurationRoot Configuration { get; } | ||||
|  | ||||
| @ -61,77 +54,24 @@ namespace Oqtane | ||||
|  | ||||
|             services.AddOptions<List<Database>>().Bind(Configuration.GetSection(SettingKeys.AvailableDatabasesSection)); | ||||
|  | ||||
|             services.AddServerSideBlazor().AddCircuitOptions(options => | ||||
|             { | ||||
|                 if (_env.IsDevelopment()) | ||||
|             services.AddServerSideBlazor() | ||||
|                 .AddCircuitOptions(options => | ||||
|                 { | ||||
|                     options.DetailedErrors = true; | ||||
|                 } | ||||
|             }); | ||||
|                     if (_env.IsDevelopment()) | ||||
|                     { | ||||
|                         options.DetailedErrors = true; | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|             // setup HttpClient for server side in a client side compatible fashion ( with auth cookie ) | ||||
|             if (!services.Any(x => x.ServiceType == typeof(HttpClient))) | ||||
|             { | ||||
|                 services.AddScoped(s => | ||||
|                 { | ||||
|                     // creating the URI helper needs to wait until the JS Runtime is initialized, so defer it. | ||||
|                     var navigationManager = s.GetRequiredService<NavigationManager>(); | ||||
|                     var client = new HttpClient(new HttpClientHandler { UseCookies = false }); | ||||
|                     client.BaseAddress = new Uri(navigationManager.Uri); | ||||
|  | ||||
|                     // set the cookies to allow HttpClient API calls to be authenticated | ||||
|                     var httpContextAccessor = s.GetRequiredService<IHttpContextAccessor>(); | ||||
|                     foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies) | ||||
|                     { | ||||
|                         client.DefaultRequestHeaders.Add("Cookie", cookie.Key + "=" + cookie.Value); | ||||
|                     } | ||||
|                     return client; | ||||
|                 }); | ||||
|             } | ||||
|             services.TryAddHttpClientWithAuthenticationCookie(); | ||||
|  | ||||
|             // register custom authorization policies | ||||
|             services.AddAuthorizationCore(options => | ||||
|             { | ||||
|                 options.AddPolicy(PolicyNames.ViewPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ViewModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ViewFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View))); | ||||
|                 options.AddPolicy(PolicyNames.EditFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit))); | ||||
|                 options.AddPolicy(PolicyNames.ListFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse))); | ||||
|             }); | ||||
|             services.AddOqtaneAuthorizationPolicies(); | ||||
|  | ||||
|             // register scoped core services | ||||
|             services.AddScoped<SiteState>(); | ||||
|             services.AddScoped<IAuthorizationHandler, PermissionHandler>(); | ||||
|             services.AddScoped<IInstallationService, InstallationService>(); | ||||
|             services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>(); | ||||
|             services.AddScoped<IThemeService, ThemeService>(); | ||||
|             services.AddScoped<IAliasService, AliasService>(); | ||||
|             services.AddScoped<ITenantService, TenantService>(); | ||||
|             services.AddScoped<ISiteService, SiteService>(); | ||||
|             services.AddScoped<IPageService, PageService>(); | ||||
|             services.AddScoped<IModuleService, ModuleService>(); | ||||
|             services.AddScoped<IPageModuleService, PageModuleService>(); | ||||
|             services.AddScoped<IUserService, UserService>(); | ||||
|             services.AddScoped<IProfileService, ProfileService>(); | ||||
|             services.AddScoped<IRoleService, RoleService>(); | ||||
|             services.AddScoped<IUserRoleService, UserRoleService>(); | ||||
|             services.AddScoped<ISettingService, SettingService>(); | ||||
|             services.AddScoped<IPackageService, PackageService>(); | ||||
|             services.AddScoped<ILogService, LogService>(); | ||||
|             services.AddScoped<IJobService, JobService>(); | ||||
|             services.AddScoped<IJobLogService, JobLogService>(); | ||||
|             services.AddScoped<INotificationService, NotificationService>(); | ||||
|             services.AddScoped<IFolderService, FolderService>(); | ||||
|             services.AddScoped<IFileService, FileService>(); | ||||
|             services.AddScoped<ISiteTemplateService, SiteTemplateService>(); | ||||
|             services.AddScoped<ISqlService, SqlService>(); | ||||
|             services.AddScoped<ISystemService, SystemService>(); | ||||
|             services.AddScoped<ILocalizationService, LocalizationService>(); | ||||
|             services.AddScoped<ILanguageService, LanguageService>(); | ||||
|             services.AddScoped<IDatabaseService, DatabaseService>(); | ||||
|             services.AddScoped<ISyncService, SyncService>(); | ||||
|             services.AddScoped<IAuthorizationHandler, PermissionHandler>() | ||||
|                 .AddOqtaneScopedServices(); | ||||
|  | ||||
|             services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | ||||
|  | ||||
| @ -141,44 +81,12 @@ namespace Oqtane | ||||
|                 .AddDefaultTokenProviders() | ||||
|                 .AddClaimsPrincipalFactory<ClaimsPrincipalFactory<IdentityUser>>(); // role claims | ||||
|  | ||||
|             services.Configure<IdentityOptions>(options => | ||||
|             { | ||||
|                 // Password settings | ||||
|                 options.Password.RequireDigit = false; | ||||
|                 options.Password.RequiredLength = 6; | ||||
|                 options.Password.RequireNonAlphanumeric = false; | ||||
|                 options.Password.RequireUppercase = false; | ||||
|                 options.Password.RequireLowercase = false; | ||||
|  | ||||
|                 // Lockout settings | ||||
|                 options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); | ||||
|                 options.Lockout.MaxFailedAccessAttempts = 10; | ||||
|                 options.Lockout.AllowedForNewUsers = true; | ||||
|  | ||||
|                 // User settings | ||||
|                 options.User.RequireUniqueEmail = false; | ||||
|             }); | ||||
|             services.ConfigureOqtaneIdentityOptions(); | ||||
|  | ||||
|             services.AddAuthentication(Constants.AuthenticationScheme) | ||||
|                 .AddCookie(Constants.AuthenticationScheme); | ||||
|  | ||||
|             services.ConfigureApplicationCookie(options => | ||||
|             { | ||||
|                 options.Cookie.HttpOnly = false; | ||||
|                 options.Cookie.SameSite = SameSiteMode.Strict; | ||||
|                 options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; | ||||
|                 options.Events.OnRedirectToLogin = context => | ||||
|                 { | ||||
|                     context.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                     return Task.CompletedTask; | ||||
|                 }; | ||||
|                 options.Events.OnRedirectToAccessDenied = context => | ||||
|                 { | ||||
|                     context.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                     return Task.CompletedTask; | ||||
|                 }; | ||||
|                 options.Events.OnValidatePrincipal = PrincipalValidator.ValidateAsync; | ||||
|             }); | ||||
|             services.ConfigureOqtaneCookieOptions(); | ||||
|  | ||||
|             services.AddAntiforgery(options => | ||||
|             { | ||||
| @ -190,51 +98,18 @@ namespace Oqtane | ||||
|             }); | ||||
|  | ||||
|             // register singleton scoped core services | ||||
|             services.AddSingleton(Configuration); | ||||
|             services.AddSingleton<IInstallationManager, InstallationManager>(); | ||||
|             services.AddSingleton<ISyncManager, SyncManager>(); | ||||
|             services.AddSingleton<IDatabaseManager, DatabaseManager>(); | ||||
|             services.AddSingleton<IConfigManager, ConfigManager>(); | ||||
|             services.AddSingleton(Configuration) | ||||
|                 .AddOqtaneSingletonServices(); | ||||
|  | ||||
|             // install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain ) | ||||
|             InstallationManager.InstallPackages(_env.WebRootPath, _env.ContentRootPath); | ||||
|  | ||||
|             // register transient scoped core services | ||||
|             services.AddTransient<ITenantManager, TenantManager>(); | ||||
|             services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>(); | ||||
|             services.AddTransient<IThemeRepository, ThemeRepository>(); | ||||
|             services.AddTransient<IUserPermissions, UserPermissions>(); | ||||
|             services.AddTransient<IAliasRepository, AliasRepository>(); | ||||
|             services.AddTransient<ITenantRepository, TenantRepository>(); | ||||
|             services.AddTransient<ISiteRepository, SiteRepository>(); | ||||
|             services.AddTransient<IPageRepository, PageRepository>(); | ||||
|             services.AddTransient<IModuleRepository, ModuleRepository>(); | ||||
|             services.AddTransient<IPageModuleRepository, PageModuleRepository>(); | ||||
|             services.AddTransient<IUserRepository, UserRepository>(); | ||||
|             services.AddTransient<IProfileRepository, ProfileRepository>(); | ||||
|             services.AddTransient<IRoleRepository, RoleRepository>(); | ||||
|             services.AddTransient<IUserRoleRepository, UserRoleRepository>(); | ||||
|             services.AddTransient<IPermissionRepository, PermissionRepository>(); | ||||
|             services.AddTransient<ISettingRepository, SettingRepository>(); | ||||
|             services.AddTransient<ILogRepository, LogRepository>(); | ||||
|             services.AddTransient<ILogManager, LogManager>(); | ||||
|             services.AddTransient<ILocalizationManager, LocalizationManager>(); | ||||
|             services.AddTransient<IJobRepository, JobRepository>(); | ||||
|             services.AddTransient<IJobLogRepository, JobLogRepository>(); | ||||
|             services.AddTransient<INotificationRepository, NotificationRepository>(); | ||||
|             services.AddTransient<IFolderRepository, FolderRepository>(); | ||||
|             services.AddTransient<IFileRepository, FileRepository>(); | ||||
|             services.AddTransient<ISiteTemplateRepository, SiteTemplateRepository>(); | ||||
|             services.AddTransient<ISqlRepository, SqlRepository>(); | ||||
|             services.AddTransient<IUpgradeManager, UpgradeManager>(); | ||||
|             services.AddTransient<ILanguageRepository, LanguageRepository>(); | ||||
|             // obsolete - replaced by ITenantManager | ||||
|             services.AddTransient<ITenantResolver, TenantResolver>(); | ||||
|             services.AddOqtaneTransientServices(); | ||||
|  | ||||
|             // load the external assemblies into the app domain, install services | ||||
|             services.AddOqtane(_runtime, _supportedCultures); | ||||
|             services.AddDbContext<MasterDBContext>(options => { }); | ||||
|             services.AddDbContext<TenantDBContext>(options => { }); | ||||
|             services.AddOqtaneDbContext(); | ||||
|  | ||||
|  | ||||
|             services.AddMvc() | ||||
| @ -242,10 +117,7 @@ namespace Oqtane | ||||
|                 .AddOqtaneApplicationParts() // register any Controllers from custom modules | ||||
|                 .ConfigureOqtaneMvc(); // any additional configuration from IStart classes. | ||||
|  | ||||
|             if (_useSwagger) | ||||
|             { | ||||
|                 services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Oqtane", Version = "v1"}); }); | ||||
|             } | ||||
|             services.TryAddSwagger(_useSwagger); | ||||
|         } | ||||
|  | ||||
|         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker