using System; using System.IO; using System.Linq; 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.AspNetCore.Mvc.Formatters; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; using Oqtane.Infrastructure; using Oqtane.Repository; using Oqtane.Security; using Oqtane.Services; using Oqtane.Shared; namespace Oqtane { public class Startup { public IConfigurationRoot Configuration { get; } private string _webRoot; public Startup(IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); Configuration = builder.Build(); _webRoot = env.WebRootPath; AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(env.ContentRootPath, "Data")); } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddMvc().AddNewtonsoftJson(); services.AddServerSideBlazor(); // 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(); var httpContextAccessor = s.GetRequiredService(); 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; }); } // register authorization services services.AddAuthorizationCore(options => { options.AddPolicy("ViewPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); options.AddPolicy("EditPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit))); options.AddPolicy("ViewModule", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View))); options.AddPolicy("EditModule", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit))); options.AddPolicy("ViewFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View))); options.AddPolicy("EditFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit))); options.AddPolicy("ListFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse))); }); // register scoped core services services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddSingleton(); services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection") .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()) )); services.AddDbContext(options => { }); services.AddIdentityCore(options => { }) .AddEntityFrameworkStores() .AddSignInManager() .AddDefaultTokenProviders(); services.Configure(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.AddAuthentication(IdentityConstants.ApplicationScheme) .AddCookie(IdentityConstants.ApplicationScheme); services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = false; options.Events.OnRedirectToLogin = context => { context.Response.StatusCode = 401; return Task.CompletedTask; }; }); // register custom claims principal factory for role claims services.AddTransient, ClaimsPrincipalFactory>(); // register singleton scoped core services services.AddSingleton(Configuration); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); // install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain ) InstallationManager.UnpackPackages("Modules,Themes", _webRoot); // register transient scoped core services services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); // load the external assemblies into the app domain services.AddOqtaneModules(); services.AddOqtaneThemes(); services.AddOqtaneSiteTemplates(); services.AddMvc() .AddOqtaneApplicationParts() // register any Controllers from custom modules .AddNewtonsoftJson(); services.AddOqtaneServices(); services.AddOqtaneHostedServices(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" }); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseWebAssemblyDebugging(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseBlazorFrameworkFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Oqtane V1"); }); app.UseEndpoints(endpoints => { endpoints.MapBlazorHub(); endpoints.MapControllers(); endpoints.MapFallbackToPage("/_Host"); }); } } }