예제 #1
0
        private void ConfigureLlblgenPro()
        {
            var dbContextList = DbContextList.DeserializeFromFile(Path.Combine(WebHostEnvironment.ContentRootPath, Program.ConfigurationFolder, $"DbContextList.{WebHostEnvironment.EnvironmentName}.config"));

            foreach (var dbContext in dbContextList)
            {
                var connectionString = Configuration.GetConnectionString(dbContext.ConnectionKey);
                RuntimeConfiguration.AddConnectionString(dbContext.ConnectionKey, connectionString);
                // Enable low-level (result set) caching when specified in selected queries
                // The cache of a query can be overwritten using property 'OverwriteIfPresent'
                CacheController.RegisterCache(connectionString, new ResultsetCache());
                CacheController.CachingEnabled = true;
            }

            //RuntimeConfiguration.SetDependencyInjectionInfo(new[] { typeof(TournamentManager.EntityValidators.UserEntityValidator).Assembly }, new[] { "TournamentManager.Validators" });

            if (WebHostEnvironment.IsProduction())
            {
                RuntimeConfiguration.ConfigureDQE <SD.LLBLGen.Pro.DQE.SqlServer.SQLServerDQEConfiguration>(c => c
                                                                                                           .SetTraceLevel(TraceLevel.Off)
                                                                                                           .AddDbProviderFactory(typeof(System.Data.SqlClient.SqlClientFactory)));
            }
            else
            {
                RuntimeConfiguration.ConfigureDQE <SD.LLBLGen.Pro.DQE.SqlServer.SQLServerDQEConfiguration>(c => c
                                                                                                           .SetTraceLevel(TraceLevel.Verbose)
                                                                                                           .AddDbProviderFactory(typeof(System.Data.SqlClient.SqlClientFactory)));

                RuntimeConfiguration.Tracing.SetTraceLevel("ORMPersistenceExecution", TraceLevel.Verbose);
                RuntimeConfiguration.Tracing.SetTraceLevel("ORMPlainSQLQueryExecution", TraceLevel.Verbose);
            }
        }
예제 #2
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(ApplicationBuilder app, WebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // 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.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            }
        }
예제 #3
0
        public static IApplicationBuilder Create(Action <IServiceCollection> configure = null)
        {
            var diagnoticListener = new DiagnosticListener("FeatherHttp");
            var whe      = new WebHostEnvironment();
            var services = new ServiceCollection()
                           .AddRouting()
                           .AddLogging()
                           .AddOptions()
                           .AddSingleton(diagnoticListener)
                           .AddSingleton <DiagnosticSource>(diagnoticListener)
                           .AddSingleton <IServer, KestrelServer>()
                           .AddSingleton <IConnectionListenerFactory, SocketTransportFactory>()
                           .AddSingleton <IWebHostEnvironment>(whe);

            services.AddOptions <KestrelServerOptions>()
            .Configure <IServiceProvider>((o, sp) =>
            {
                o.ApplicationServices = sp;
            });


            configure?.Invoke(services);

            return(new ApplicationBuilder(services.BuildServiceProvider()));
        }
        public void ApplyEnvironmentSettingsUsesTheCorrectKeysAndProperties()
        {
            var originalEnvironment = new WebHostEnvironment
            {
                ApplicationName         = WebHostDefaults.ApplicationKey,
                EnvironmentName         = WebHostDefaults.EnvironmentKey,
                ContentRootPath         = WebHostDefaults.ContentRootKey,
                WebRootPath             = WebHostDefaults.WebRootKey,
                ContentRootFileProvider = Mock.Of <IFileProvider>(),
                WebRootFileProvider     = Mock.Of <IFileProvider>(),
            };

            var settings = new Dictionary <string, string>();
            var webHostBuilderEnvironment = new WebHostEnvironment();

            originalEnvironment.ApplyEnvironmentSettings(new TestWebHostBuilder(settings, webHostBuilderEnvironment));

            Assert.Equal(WebHostDefaults.ApplicationKey, settings[WebHostDefaults.ApplicationKey]);
            Assert.Equal(WebHostDefaults.EnvironmentKey, settings[WebHostDefaults.EnvironmentKey]);
            Assert.Equal(WebHostDefaults.ContentRootKey, settings[WebHostDefaults.ContentRootKey]);
            Assert.Equal(WebHostDefaults.WebRootKey, settings[WebHostDefaults.WebRootKey]);

            Assert.Equal(WebHostDefaults.ApplicationKey, webHostBuilderEnvironment.ApplicationName);
            Assert.Equal(WebHostDefaults.EnvironmentKey, webHostBuilderEnvironment.EnvironmentName);
            Assert.Equal(WebHostDefaults.ContentRootKey, webHostBuilderEnvironment.ContentRootPath);
            Assert.Equal(WebHostDefaults.WebRootKey, webHostBuilderEnvironment.WebRootPath);

            Assert.Same(originalEnvironment.ContentRootFileProvider, webHostBuilderEnvironment.ContentRootFileProvider);
            Assert.Same(originalEnvironment.WebRootFileProvider, webHostBuilderEnvironment.WebRootFileProvider);
        }
예제 #5
0
        private void ConfigureLlblgenPro(TenantStore tenantStore)
        {
            foreach (var tenant in tenantStore.GetTenants().Values)
            {
                var connectionString = Configuration.GetConnectionString(tenant.DbContext.ConnectionKey);
                RuntimeConfiguration.AddConnectionString(tenant.DbContext.ConnectionKey, connectionString);
                // Enable low-level (result set) caching when specified in selected queries
                // The cache of a query can be overwritten using property 'OverwriteIfPresent'
                CacheController.RegisterCache(connectionString, new ResultsetCache());
                CacheController.CachingEnabled = true;
            }

            if (WebHostEnvironment.IsProduction())
            {
                RuntimeConfiguration.ConfigureDQE <SD.LLBLGen.Pro.DQE.SqlServer.SQLServerDQEConfiguration>(c => c
                                                                                                           .SetTraceLevel(TraceLevel.Off)
                                                                                                           .AddDbProviderFactory(typeof(System.Data.SqlClient.SqlClientFactory)));
            }
            else
            {
                RuntimeConfiguration.ConfigureDQE <SD.LLBLGen.Pro.DQE.SqlServer.SQLServerDQEConfiguration>(c => c
                                                                                                           .SetTraceLevel(TraceLevel.Verbose)
                                                                                                           .AddDbProviderFactory(typeof(System.Data.SqlClient.SqlClientFactory)));

                RuntimeConfiguration.Tracing.SetTraceLevel("ORMPersistenceExecution", TraceLevel.Verbose);
                RuntimeConfiguration.Tracing.SetTraceLevel("ORMPlainSQLQueryExecution", TraceLevel.Verbose);
            }
        }
예제 #6
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            if (WebHostEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors("DevelopmentPolicy");

            app.UseSwagger();

            app.UseSwaggerUI(setupAction =>
            {
                setupAction.SwaggerEndpoint(
                    $"{(WebHostEnvironment.IsDevelopment() ? "" : API_PREFIX)}/swagger/MyFinanceApiOpenAPISecification/swagger.json",
                    "MyFinanceAPI");
                setupAction.RoutePrefix = "";
            });

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
예제 #7
0
 public BootstrapHostBuilder(Configuration configuration, WebHostEnvironment webHostEnvironment)
 {
     _configuration = configuration;
     _environment   = webHostEnvironment;
     _context       = new HostBuilderContext(Properties)
     {
         Configuration      = configuration,
         HostingEnvironment = webHostEnvironment
     };
 }
예제 #8
0
        public void Configure(IApplicationBuilder app)
        {
            if (WebHostEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    TelemetryClient telemetryClient = context.RequestServices.GetRequiredService <TelemetryClient>(); // You can inject TelemetryClient in controllers and services to provide additional data to app insights sdk.

                    using (IOperationHolder <DependencyTelemetry> exportExcelOperation = telemetryClient.StartOperation <DependencyTelemetry>("ExportToExcel"))
                    {
                        exportExcelOperation.Telemetry.Type   = "Background";
                        exportExcelOperation.Telemetry.Target = "ApplicationServer";

                        try
                        {
                            await Task.Delay(1000);
                            telemetryClient.TrackTrace($"done {30}%");
                            await Task.Delay(1000);
                            telemetryClient.TrackTrace($"done {60}%");
                            await Task.Delay(1000);
                            telemetryClient.TrackTrace($"done {100}%");
                        }
                        catch (Exception exp)
                        {
                            telemetryClient.TrackException(exp);
                            throw;
                        }
                        finally
                        {
                            telemetryClient.StopOperation(exportExcelOperation);
                        }
                    }

                    telemetryClient.TrackEvent("MyEvent", new Dictionary <string, string>
                    {
                        { "prop1", "1" },
                        { "prop2", "2" }
                    });

                    ILogger <ClaimsIdentity> logger = context.RequestServices.GetRequiredService <ILogger <ClaimsIdentity> >(); // 3rd party libraries which relies on MS.Ext.Logging will also be captured by app insights sdk.

                    logger.LogWarning("User {user} was logged in...", "admin");

                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
예제 #9
0
        public override void Configure(IFunctionsHostBuilder builder)
        {
            Environment.SetEnvironmentVariable("BASEDIR", AppContext.BaseDirectory);
            Environment.SetEnvironmentVariable("ConnectionStrings:ClientsDbConnectionString", "Server=(local);Database=Clients;Trusted_Connection=True;");
            Environment.SetEnvironmentVariable("DisableAuthenticationAndAuthorization", "false");
            Environment.SetEnvironmentVariable("TokenProviderOptions:Issuer", "https://dev-318215.okta.com/oauth2/aus15ubkj0WHGsqEV4x6");
            Environment.SetEnvironmentVariable("TokenProviderOptions:Audience", "UserManagement");

            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Information()
                         .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                         .Enrich.FromLogContext()
                         .WriteTo.Console()
                         .CreateLogger();

            var loggerFactory = new SerilogLoggerFactory(Log.Logger, false);

            builder.Services.AddSingleton <ILoggerFactory>(loggerFactory);

            var configuration = new ConfigurationBuilder()
                                .AddEnvironmentVariables()
                                .Build();

            var services           = new ServiceCollection();
            var diagnosticListener = new DiagnosticListener("Microsoft.AspNetCore");

            services.AddSingleton <DiagnosticSource>(diagnosticListener);
            services.AddSingleton(diagnosticListener);
            services.AddSingleton <ObjectPoolProvider>(new DefaultObjectPoolProvider());
            services.AddSingleton <ILoggerFactory>(loggerFactory);
            services.AddSingleton <IConfiguration>(configuration);
            services.AddLogging();

            var startup = new ClientApi.Startup(configuration);

            startup.ConfigureServices(services);

            var environment = new WebHostEnvironment {
                EnvironmentName = configuration["Environment"]
            };

            builder.Services.AddSingleton <IApplicationBuilder>(provider =>
            {
                var serviceProvider    = provider.GetService <ServiceProvider>();
                var applicationBuilder = new ApplicationBuilder(serviceProvider, new FeatureCollection());

                startup.Configure(applicationBuilder, environment);
                return(applicationBuilder);
            });

            builder.Services.AddScoped(provider => services.BuildServiceProvider());
            builder.Services.AddSingleton(provider => provider.GetService <IApplicationBuilder>().Build());
        }
예제 #10
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddInfrastructure(WebHostEnvironment.IsDevelopment());
            services.AddPersistence(Configuration);
            services.AddApplication();

            services.AddControllers();

            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });
        }
예제 #11
0
        public void RelativePathsAreMappedToFullPaths()
        {
            var environment      = new WebHostEnvironment();
            var relativeRootPath = "some-relative-path";
            var relativeSubPath  = "some-other-relative-path";
            var fullContentRoot  = Path.Combine(AppContext.BaseDirectory, relativeRootPath);

            // ContentRootPath is mapped relative to AppContext.BaseDirectory
            environment.ContentRootPath = relativeRootPath;
            Assert.Equal(fullContentRoot, environment.ContentRootPath);

            // WebRootPath is mapped relative to ContentRootPath
            environment.WebRootPath = relativeSubPath;
            Assert.Equal(Path.Combine(fullContentRoot, relativeSubPath), environment.WebRootPath);
        }
예제 #12
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            if (WebHostEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
예제 #13
0
        public WebApplicationHostBuilder(IHostBuilder hostBuilder)
        {
            _hostBuilder = hostBuilder;

            Services = new ServiceCollection();

            // HACK: MVC and Identity do this horrible thing to get the hosting environment as an instance
            // from the service collection before it is built. That needs to be fixed...
            Environment = new WebHostEnvironment();
            Services.AddSingleton(Environment);

            // REVIEW: Since the configuration base is tied to the content root, it needs to be specified as part of
            // builder creation. It's not changing in the current design.
            Configuration = new ConfigurationBuilder().SetBasePath(Environment.ContentRootPath);
            Logging       = new LoggingBuilder(Services);
        }
예제 #14
0
        private void ConfigureLoggers(IServiceCollection services)
        {
            var builder = new ApplicationLoggerBuilder();

            IConfiguration configuration = new ConfigurationBuilder().Build();

            builder.ConfigureLoggingServices(configuration, services);

            var hostingEnvironment = new WebHostEnvironment()
            {
                EnvironmentName = this.options.EnvironmentName
            };

            const LogLevel minLevel = LogLevel.Trace;

            services.AddLogging(logging =>
            {
                logging.ClearProviders();

                if (options.LogToTestOutput)
                {
                    logging.AddXunit(output, minLevel);
                }
                if (options.LogToConsole)
                {
                    logging.AddConsole();
                }
                if (options.LogToSerilog)
                {
                    var loggerConfiguration = new LoggerConfiguration();
                    builder.ConfigureLogging(loggerConfiguration, hostingEnvironment);

                    logging.AddSerilog(loggerConfiguration.CreateLogger());
                }
            });

            services.PostConfigureAll <ConsoleLoggerOptions>(options =>
            {
                options.IncludeScopes = true;
            });
            services.PostConfigureAll <LoggerFilterOptions>(options =>
            {
                options.MinLevel = minLevel;
                options.Rules.Clear();
            });
        }
예제 #15
0
        public void SettingPathsSetsContentProviders()
        {
            var environment = new WebHostEnvironment();
            var tempPath    = Path.GetTempPath();

            environment.ContentRootPath = tempPath;
            environment.WebRootPath     = tempPath;

            Assert.Equal(tempPath, environment.WebRootPath);
            Assert.Equal(tempPath, environment.ContentRootPath);

            Assert.IsType <PhysicalFileProvider>(environment.ContentRootFileProvider);
            Assert.IsType <PhysicalFileProvider>(environment.WebRootFileProvider);

            Assert.Equal(EnsureTrailingSlash(tempPath), ((PhysicalFileProvider)environment.ContentRootFileProvider).Root);
            Assert.Equal(EnsureTrailingSlash(tempPath), ((PhysicalFileProvider)environment.WebRootFileProvider).Root);
        }
예제 #16
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddTransient <IImageService>((service) =>
                                                  new ImageService(new ImageSaver(), new ImageChecker()));

            if (WebHostEnvironment.IsDevelopment())
            {
                services.AddDbContext <ImageContext>((options) =>
                                                     options.UseInMemoryDatabase("ImagesDB"));
            }
            else
            {
                services.AddDbContext <ImageContext>((options) =>
                                                     options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            }
        }
예제 #17
0
        public void Configure(IApplicationBuilder applicationBuilder)
        {
            if (WebHostEnvironment.IsDevelopment())
            {
                applicationBuilder
                .UseDeveloperExceptionPage()
                .UseSwagger()
                .UseSwaggerUI(c => c.SwaggerEndpoint($"/swagger/{SwaggerVersion}/swagger.json", SwaggerName));
            }

            applicationBuilder
            .UseMiddleware <ExceptionMiddleware>()
            .UseHttpsRedirection()
            .UseRouting()
            .UseAuthentication()
            .UseAuthorization()
            .UseEndpoints(endpoints => endpoints.MapControllers());
        }
예제 #18
0
        public void SetContentRootAfterRelativeWebRoot()
        {
            var environment = new WebHostEnvironment();
            var webRootPath = "some-relative-path";
            var tempPath    = Path.GetTempPath();

            environment.WebRootPath = webRootPath;

            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), webRootPath), environment.WebRootPath);
            Assert.Equal(Directory.GetCurrentDirectory(), environment.ContentRootPath);

            // Setting the ContentRootPath after setting a relative WebRootPath
            environment.ContentRootPath = tempPath;

            Assert.Equal(tempPath, environment.ContentRootPath);
            Assert.Equal(EnsureTrailingSlash(tempPath), ((PhysicalFileProvider)environment.ContentRootFileProvider).Root);
            Assert.Equal(Path.Combine(tempPath, webRootPath), environment.WebRootPath);
        }
예제 #19
0
        /// <summary>
        /// Build configuration from AppSettings, Environment Variables, Azure Key Valut and (User Secrets - DEV only).
        /// </summary>
        /// <returns><see cref="IConfiguration"/></returns>
        private IConfiguration BuildConfiguration()
        {
            var configurationBuilder = new ConfigurationBuilder();

            configurationBuilder.SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables()
            .AddUserSecrets(typeof(Startup).Assembly)
            .AddAzureKeyVaultIfAvailable();

            if (WebHostEnvironment.IsDevelopment())
            {
                // Re-add User secrets so it takes precedent for local development
                configurationBuilder.AddUserSecrets(typeof(Startup).Assembly);
            }

            return(configurationBuilder.Build());
        }
예제 #20
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCompression();
            services.AddDbContext <ApplicationDbContext>(options =>
                                                         options.UseSqlServer(
                                                             Configuration.GetConnectionString("DefaultConnection")));
            services.AddIdentity <ApplicationUser, ApplicationRole>()
            .AddEntityFrameworkStores <ApplicationDbContext>();
            services.AddInfrastructure();
            var mvcBuilder = services.AddRazorPages();

#if DEBUG
            if (WebHostEnvironment.IsDevelopment())
            {
                mvcBuilder.AddRazorRuntimeCompilation();
            }
#endif
        }
예제 #21
0
        public void ApplyEnvironmentSettingsUsesTheCorrectKeys()
        {
            var env = new WebHostEnvironment
            {
                ApplicationName = WebHostDefaults.ApplicationKey,
                EnvironmentName = WebHostDefaults.EnvironmentKey,
                ContentRootPath = WebHostDefaults.ContentRootKey,
                WebRootPath     = WebHostDefaults.WebRootKey,
            };

            var settings = new Dictionary <string, string>();

            env.ApplyEnvironmentSettings(new TestWebHostBuilder(settings));

            Assert.Equal(WebHostDefaults.ApplicationKey, settings[WebHostDefaults.ApplicationKey]);
            Assert.Equal(WebHostDefaults.EnvironmentKey, settings[WebHostDefaults.EnvironmentKey]);
            Assert.Equal(WebHostDefaults.ContentRootKey, settings[WebHostDefaults.ContentRootKey]);
            Assert.Equal(WebHostDefaults.WebRootKey, settings[WebHostDefaults.WebRootKey]);
        }
예제 #22
0
        public void UnsettingPathsFallsBackToDefaults()
        {
            var environment        = new WebHostEnvironment();
            var defaultWebRootPath = Path.Combine(environment.ContentRootPath, "wwwroot");
            var webRootPath        = Path.GetTempPath();

            environment.WebRootPath = webRootPath;

            Assert.Equal(webRootPath, environment.WebRootPath);
            Assert.Equal(EnsureTrailingSlash(webRootPath), ((PhysicalFileProvider)environment.WebRootFileProvider).Root);

            // Setting WebRootPath to fallsback to default
            environment.WebRootPath = null;
            Assert.Equal(defaultWebRootPath, environment.WebRootPath);

            // Setting ContentRootPath to null falls back to CurrentDirectory
            environment.ContentRootPath = null;
            Assert.Equal(Directory.GetCurrentDirectory(), environment.ContentRootPath);
            Assert.Equal(EnsureTrailingSlash(Directory.GetCurrentDirectory()), ((PhysicalFileProvider)environment.ContentRootFileProvider).Root);
        }
예제 #23
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            // In production, the React files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });

            if (WebHostEnvironment.IsEnvironment("Test") || WebHostEnvironment.IsDevelopment())
            {
                services.AddDbContext <CoronaMedContext>(opt => opt.UseInMemoryDatabase("CoronaMedDB"));
            }
            else
            {
                services.AddDbContext <CoronaMedContext>(options => options.UseSqlServer(Configuration["CoronaMed_Database"]));
            }

            #region Swagger
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version = "v1",
                    Title   = "CornaMed API"
                });
            });
            #endregion

            #region IOC
            //Repositories
            services.AddTransient <IPartnerRepository, PartnerRepository>();

            //CommandHandler
            services.AddTransient <IPartnerCommandHandler, PartnerCommandHandler>();

            #endregion
        }
        public void ApplyConfigurationSettingsUsesTheCorrectKeys()
        {
            var configBuilder = new ConfigurationBuilder();

            configBuilder.AddInMemoryCollection(new[]
            {
                new KeyValuePair <string, string>(WebHostDefaults.ApplicationKey, WebHostDefaults.ApplicationKey),
                new KeyValuePair <string, string>(WebHostDefaults.EnvironmentKey, WebHostDefaults.EnvironmentKey),
                new KeyValuePair <string, string>(WebHostDefaults.ContentRootKey, WebHostDefaults.ContentRootKey),
                new KeyValuePair <string, string>(WebHostDefaults.WebRootKey, WebHostDefaults.WebRootKey),
            });

            var env = new WebHostEnvironment();

            // Basically call ApplyConfigurationSettings(config) but without creating PhysicalFileProviders.
            env.ReadConfigurationSettings(configBuilder.Build());

            Assert.Equal(WebHostDefaults.ApplicationKey, env.ApplicationName);
            Assert.Equal(WebHostDefaults.EnvironmentKey, env.EnvironmentName);
            Assert.Equal(WebHostDefaults.ContentRootKey, env.ContentRootPath);
            Assert.Equal(WebHostDefaults.WebRootKey, env.WebRootPath);
        }
예제 #25
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            if (WebHostEnvironment.IsDevelopment())
            {
                services.AddCors(o =>
                {
                    o.AddDefaultPolicy(builder =>
                    {
                        builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
                    });
                });
            }

            services.AddControllers().AddFluentValidation();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Hahn.ApplicationProcess.Application", Version = "v1"
                });
                c.ExampleFilters();
            })
            .AddSwaggerExamplesFromAssemblyOf <Startup>();
        }
예제 #26
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddMvc(options =>
            {
                options.EnableEndpointRouting = false;
            }).AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.IgnoreNullValues = true;
            });

            services.AddResponseCompression(x =>
            {
                x.Providers.Add <GzipCompressionProvider>();
            });

            services.Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            services.Configure <IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            if (!WebHostEnvironment.IsProduction())
            {
                #region Configuração do Cors CrossOrigins
                services.AddCors(options =>
                {
                    options.AddPolicy("AllowAll",
                                      builder =>
                    {
                        builder
                        .AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .DisallowCredentials();
                    });
                });
                #endregion
            }

            #region Configuração do Swagger
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(
                    "v1",
                    new OpenApiInfo
                {
                    Version        = "v1",
                    Title          = "Api",
                    Description    = "Poc SignalR",
                    TermsOfService = new Uri("https://example.com/terms"),
                    Contact        = new OpenApiContact
                    {
                        Name  = "Uirá Peixoto",
                        Email = string.Empty,
                        Url   = new Uri("https://github.com/uirapeixoto"),
                    }
                }
                    );
            });
            #endregion

            services.AddSignalR();
        }
예제 #27
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            //.AddJsonOptions(options =>
            //{
            //    options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
            //    options.JsonSerializerOptions.WriteIndented = true;
            //});
            services.AddRazorPages();
            services.AddCors();
            //services.AddMvc(options => options.Filters.Add(new AuthorizeFilter()))
            services.AddAutoMapperProfile();
            services.Configure <RouteOptions>(options => options.AppendTrailingSlash = true);
            var appSettingsSection = Configuration.GetSection("AppSettings");
            var appSettings        = appSettingsSection.Get <AppSettings>();
            var mqttSettings       = Configuration.GetSection("MQTTSettings").Get <MQTTSettings>();

            if (WebHostEnvironment.IsDevelopment())
            {
                mqttSettings.ClientSettings.Id = System.Guid.NewGuid().ToString();
            }
            //string apiBaseUrlAccount = appSettings.MyWebApi.BaseUrlAccount;
            //string apiBaseUrlEmail = appSettings.MyWebApi.BaseUrlEmail;
            //string apiBaseUrlLogging = appSettings.MyWebApi.BaseUrlLogging;
            services.Configure <AppSettings>(appSettingsSection);

            //Explicitly register the settings object by delegating to the IOptions object so that it can be accessed globally via AppServicesHelper.
            services.AddSingleton(resolver => resolver.GetRequiredService <IOptionsMonitor <AppSettings> >().CurrentValue);

            services.Configure <CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.Lax;
            });
            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.Cookie.HttpOnly    = true;
                options.Cookie.IsEssential = true;
                options.IdleTimeout        = TimeSpan.FromMinutes(15);
            });

            //services.AddDefaultIdentity<IdentityUser>().AddRoles<IdentityRole>();
            //services.AddIdentity<UserModel, RoleModel>().AddUserStore<UserModel>().AddDefaultTokenProviders();
            services.AddIdentityCore <UserModel>(options =>
            {
                //Password settings.
                options.Password.RequireDigit           = true;
                options.Password.RequiredLength         = 6;
                options.Password.RequireNonAlphanumeric = true;
                options.Password.RequireUppercase       = true;
                options.Password.RequireLowercase       = true;

                // Default Lockout settings.
                options.Lockout.DefaultLockoutTimeSpan  = TimeSpan.FromMinutes(5);
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.AllowedForNewUsers      = true;

                options.User.RequireUniqueEmail      = true;
                options.SignIn.RequireConfirmedEmail = true;
            })
            .AddRoles <RoleModel>()
            .AddSignInManager()
            .AddDefaultTokenProviders();

            //services.Configure<IdentityOptions>(options =>
            //{
            //    // Default Lockout settings.
            //    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
            //    options.Lockout.MaxFailedAccessAttempts = 5;
            //    options.Lockout.AllowedForNewUsers = true;
            //});

            // configure cookie authentication.
            //var key = Encoding.ASCII.GetBytes(appSettings.AuthenticationOptions.Secret);
            //services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            services.AddAuthentication(options =>
            {
                //x.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                //x.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;

                options.DefaultScheme             = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                //x.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                //x.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
            })
            .AddOpenIdConnect(options =>
            {
                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.Authority    = appSettings.OpenIDConnect.authority;
                options.ResponseType = OpenIdConnectResponseType.Code;
                options.UsePkce      = false;
                //options.Scope.Clear();
                //options.Scope.Add("openid");
                //options.Scope.Add("profile");
                //options.Scope.Add("email");
                options.SaveTokens = true;
                // MetadataAddress represents the Active Directory instance used to authenticate users.
                options.MetadataAddress = appSettings.OpenIDConnect.metaData;
                options.ClientId        = appSettings.OpenIDConnect.clientId;
                //options.CallbackPath = "/Account/signin-oidc";

                options.EventsType = typeof(CustomOidcAuthenticationEvents);
            })
            .AddCookie(options =>
            {
                //Authentication cookie policy.
                options.Cookie.Name         = "MyWeb.Auth";
                options.ClaimsIssuer        = appSettings.AuthenticationOptions.issuer;
                options.Cookie.HttpOnly     = true;
                options.Cookie.IsEssential  = true;
                options.Cookie.SecurePolicy = WebHostEnvironment.IsDevelopment()
                  ? CookieSecurePolicy.None : CookieSecurePolicy.Always;
                options.Cookie.SameSite  = SameSiteMode.Strict;
                options.AccessDeniedPath = "/Account/Denied";
                options.LoginPath        = "/Account/Login";
                options.LogoutPath       = "/Account/Logout";
                //options.EventsType = typeof(CustomCookieAuthenticationEvents);//If we want to overload cookie events. Also need to put this services.AddScoped<CustomCookieAuthenticationEvents>();
            });
            //.AddCookie("AuthenticationTypes.Federation", options =>
            //{
            //});
            //.AddIdentityCookies(options => { });

            //Global cookie policy
            services.Configure <CookiePolicyOptions>(options =>
            {
                //https://www.red-gate.com/simple-talk/dotnet/net-development/using-auth-cookies-in-asp-net-core/
                options.MinimumSameSitePolicy = SameSiteMode.Strict;
                options.HttpOnly = HttpOnlyPolicy.None;
                options.Secure   = WebHostEnvironment.IsDevelopment()
                  ? CookieSecurePolicy.None : CookieSecurePolicy.Always;
            });
            //services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/Login");

            //Configure authorization policies
            services.AddSingleton <IAuthorizationHandler, RoleAuthorizationHandler>();
            services.AddAuthorizationCore(x =>
            {
                //var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
                //        JwtBearerDefaults.AuthenticationScheme);
                //defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();

                x.AddPolicy(Role.Admin, p => p.Requirements.Add(new RoleAuthorizationRequirement(appSettings.AuthenticationOptions.issuer, Role.Admin)));
                //x.AddPolicy(Role.Admin, p => p.Requirements.Add(new RoleAuthorizationRequirement(OidcConstants.issuer, Role.Admin)));
                x.AddPolicy(Role.SuperUser, p => p.Requirements.Add(new RoleAuthorizationRequirement(appSettings.AuthenticationOptions.issuer, Role.SuperUser)));
                x.AddPolicy(Role.CustomApp, p => p.Requirements.Add(new RoleAuthorizationRequirement(appSettings.AuthenticationOptions.issuer, Role.Admin, Role.CustomApp)));
            });

            //Don't do this b/c then new account email confirmation tokens will also expire... leave it at the default of 24hrs.
            //Change all data Tokens to expire after 3 hours. https://docs.microsoft.com/en-us/aspnet/core/security/authentication/accconfirm?view=aspnetcore-3.1&tabs=visual-studio#change-all-data-protection-token-lifespans
            //This only affects tokens generated by the userManager and maybe the signInManager. Not the tokens we keep in our DB.
            //services.Configure<DataProtectionTokenProviderOptions>(options =>
            //    options.TokenLifespan = TimeSpan.FromHours(3)
            //    );


            //Additional services.
            services.AddHttpContextAccessor();
            services.AddAccountService();
            services.AddCustomAppReportService();
            services.AddApplicationUserService();
            services.AddApplicationRoleService();
            services.AddEmailService();
            services.AddApiLoggingService();
            services.AddAtmosphereService(mqttSettings);
            services.AddTransient <ICustomAppService, CustomAppService>();
            services.AddTransient <IUserStore <UserModel>, UserStore>();
            services.AddTransient <IRoleStore <RoleModel>, RoleStore>();
            services.AddTransient <IRazorViewToStringRenderer, RazorViewToStringRenderer>();
            //services.AddScoped<CustomCookieAuthenticationEvents>();
            services.AddScoped <CustomOidcAuthenticationEvents>();
        }
예제 #28
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app,
                              IOptions <AppSettings> settings,
                              ILoggerFactory logFactory,
                              IHttpContextAccessor accessor)
        {
            //Static services
            lib.ApplicationLogging.LoggerFactory = logFactory;
            AppServicesHelper.Services           = app.ApplicationServices;

            //AppSettings appSettings = settings.Value;

            //See Middleware order: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1#middleware-order

            if (WebHostEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // 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.UseCookiePolicy(); //The cookie policy middleware is order sensitive.

            app.UseRouting();
            // app.UseRequestLocalization();
            // app.UseCors();

            //app.ConfigureCustomExceptionMiddleware();

            app.UseSession();                    //Needs to be after UseRouting and before UseEndpoints. Needs to be before UseAuthentication and UseHttpContextItemsMiddleware since it needs the session.
            app.UseAuthentication();             //By invoking the authentication middleware, you will get a HttpContext.User property.
            app.UseHttpContextItemsMiddleware(); //Needs to be after UseAuthentication to have the cookie claims loaded and before UseAuthorization so the session can be used.
            app.UseAuthorization();

            ////If the user is not authenticated dont allow access to the folders that startwith the options below
            app.UseStaticFilesMiddleware(options =>
            {
                options.AddAuthSegment("/CustomApp");
                options.AddAuthSegment("/js/CustomApp");
                options.AddFileExtensionContentTypeMapping(".glb", "model/gltf-binary");
                options.AddFileExtensionContentTypeMapping(".webmanifest", "application/manifest+json");
                options.AddFileExtensionContentTypeMapping(".vue", "application/javascript");
            });

            app.UseRememberMeCookieSessionMiddleware(options =>
            {
                options.LoginPath = "/Account/Login";
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(name: "areas", pattern: "{area:exists}/{controller=Default}/{action=Index}/{id?}");
                //endpoints.MapAreaControllerRoute(
                //  "Admin",
                //  "Admin",
                //  "Admin/{controller=Home}/{action=Index}/{id?}");

                endpoints.MapControllers();
                endpoints.MapDefaultControllerRoute();
                //endpoints.MapRazorPages();

                //endpoints.MapControllerRoute(
                //    "default", "{controller=Home}/{action=Index}/{id?}");
            });
        }
예제 #29
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            // Add services required for using options.
            services.AddOptions();

            #region * DataProtection service configuration *

            // Usage:
            // private readonly IDataProtector protector;
            // public SomeController(IDataProtectionProvider provider)
            // {  protector = provider.CreateProtector("isolation purpose");}
            // public IActionResult Test(string input)
            // { var protectedPayload = protector.Protect(input);
            // var unprotectedPayload = protector.Unprotect(protectedPayload)
            // ...}

            // required for cookies and session cookies (will throw CryptographicException without)
            services.AddDataProtection()
            .SetApplicationName("League")
            .SetDefaultKeyLifetime(TimeSpan.FromDays(360))
            .PersistKeysToFileSystem(
                new DirectoryInfo(Path.Combine(WebHostEnvironment.ContentRootPath, "DataProtectionKeys")))
            .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration()
            {
                EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
                ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
            });

            // register the multi purpose DataProtector
            services.AddSingleton(typeof(League.DataProtection.DataProtector));

            #endregion

            // Configure form upload limits
            services.Configure <Microsoft.AspNetCore.Http.Features.FormOptions>(fo =>
            {
                fo.ValueLengthLimit         = int.MaxValue;
                fo.MultipartBodyLengthLimit = int.MaxValue;
            });

            // The default region of this app is "us", unless configured differently
            // The region info is used for country-specific data like phone numbers
            var regionInfo = new RegionInfo(Configuration.GetSection("RegionInfo").Value ?? "us");
            services.AddSingleton <RegionInfo>(regionInfo);

            // The default culture of this app is "en". Supported cultures: en, de
            CultureInfo.DefaultThreadCurrentCulture   = new CultureInfo(Configuration.GetSection("CultureInfo:Culture").Value ?? $"en-{regionInfo.TwoLetterISORegionName}");
            CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(Configuration.GetSection("CultureInfo:UiCulture").Value ?? $"en-{regionInfo.TwoLetterISORegionName}");

            // DO NOT USE `options => options.ResourcesPath = "..."` because then resource files in other locations won't be recognized (e.g. resx in the same folder as the controller class)
            services.AddLocalization();

            #region **** New Multi Tenancy (since v4.3.0) *****************************

            services.AddSingleton <TenantStore>(sp =>
            {
                var store = (TenantStore) new TenantStore(Configuration, sp.GetRequiredService <ILogger <TournamentManager.MultiTenancy.TenantStore> >())
                {
                    GetTenantConfigurationFiles = () =>
                    {
                        var configFolderFiles = Directory.GetFiles(
                            Path.Combine(WebHostEnvironment.ContentRootPath, Program.ConfigurationFolder),
                            $"Tenant.*.{WebHostEnvironment.EnvironmentName}.config", SearchOption.TopDirectoryOnly).ToList();

                        if (WebHostEnvironment.IsDevelopment())
                        {
                            configFolderFiles.AddRange(Directory.GetFiles(
                                                           Path.Combine(Program.GetSecretsFolder()),
                                                           $"Tenant.*.{WebHostEnvironment.EnvironmentName}.config", SearchOption.TopDirectoryOnly));
                        }
                        Logger.LogInformation("Tenant config files: {Config}", configFolderFiles);
                        return(configFolderFiles.ToArray());
                    }
                }.LoadTenants();

                var tenants = store.GetTenants().Values.ToList();
                if (!tenants.Any(t => t.IsDefault))
                {
                    throw new Exception("No default tenant configuration found.");
                }
                tenants.ForEach(t =>
                {
                    if (string.IsNullOrWhiteSpace(t.DbContext.ConnectionString))
                    {
                        throw new Exception($"Tenant '{t.Identifier}': Connection string for key '{t.DbContext.ConnectionKey}' not found.");
                    }
                });

                ConfigureLlblgenPro(store);

                return(store);
            });

            services.AddScoped <MultiTenancy.TenantResolver>();
            services.AddScoped <TournamentManager.MultiTenancy.ITenantContext>(sp => sp.GetRequiredService <MultiTenancy.TenantResolver>().Resolve());

            #endregion

            services.Configure <IISOptions>(options => { });

            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            // Make UrlHelper injectable to any component in the HttpContext
            services.AddScoped <IUrlHelper>(sp => {
                var actionContext = sp.GetRequiredService <IActionContextAccessor>().ActionContext;
                var factory       = sp.GetRequiredService <IUrlHelperFactory>();
                return(factory.GetUrlHelper(actionContext));
            });

            services.AddSingleton <IConfiguration>(Configuration);

            services.AddMemoryCache(); // Adds a default in-memory cache implementation
            // MUST be before AddMvc!
            services.AddSession(options =>
            {
                options.IdleTimeout        = TimeSpan.FromMinutes(60);
                options.Cookie.HttpOnly    = true;
                options.Cookie.Name        = ".sid";
                options.Cookie.IsEssential = true;
            });

            #region ** Identity and Authentication **

            var socialLogins = Configuration.GetSection(nameof(SocialLogins)).Get <SocialLogins>();
            services.AddAuthentication(options =>
            {
                options.DefaultScheme             = IdentityConstants.ApplicationScheme;
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme    = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme       = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddFacebook(options =>
            {
                options.AppId        = socialLogins.Facebook.AppId;
                options.AppSecret    = socialLogins.Facebook.AppSecret;
                options.CallbackPath = new PathString("/signin-facebook");     // this path is used by the middleware only, no route necessary
                // add the facebook picture url as an additional claim
                options.ClaimActions.MapJsonKey("urn:facebook:picture", "picture", "picture.data.url");
                options.SaveTokens             = true;
                options.CorrelationCookie.Name = ".CorrAuth.League";
                options.Events.OnRemoteFailure = context =>
                {
                    // Note: If this delegate is missing, errors with the external login lead to a System.Exception: access_denied;Description=Permissions error
                    var qsParameter =
                        new Dictionary <string, string>
                    {
                        { "remoteError", context.Request.Query["error"].ToString() },
                    }.Where(item => !string.IsNullOrEmpty(item.Value)).ToDictionary(i => i.Key, i => i.Value);
                    // joins query strings from RedirectUri and qsParameter
                    var redirectUri = QueryHelpers.AddQueryString(context.Properties?.RedirectUri ?? "/", qsParameter);
                    context.Response.Redirect(redirectUri);
                    context.HandleResponse();
                    return(Task.CompletedTask);
                };
            })
            .AddGoogle(options =>
            {
                options.ClientId     = socialLogins.Google.ClientId;
                options.ClientSecret = socialLogins.Google.ClientSecret;
                options.CallbackPath = new PathString("/signin-google");     // this path is used by the middleware only, no route necessary
                options.ClaimActions.MapJsonKey("urn:google:picture", "picture", "url");;
                options.SaveTokens             = true;
                options.CorrelationCookie.Name = ".CorrAuth.League";
                options.Events.OnRemoteFailure = context =>
                {
                    // Note: If this delegate is missing, errors with the external login lead to a System.Exception: access_denied;Description=Permissions error
                    var qsParameter =
                        new Dictionary <string, string>
                    {
                        { "remoteError", context.Request.Query["error"].ToString() },
                    }.Where(item => !string.IsNullOrEmpty(item.Value)).ToDictionary(i => i.Key, i => i.Value);
                    // joins query strings from RedirectUri and qsParameter
                    var redirectUri = QueryHelpers.AddQueryString(context.Properties?.RedirectUri ?? "/", qsParameter);
                    context.Response.Redirect(redirectUri);
                    context.HandleResponse();
                    return(Task.CompletedTask);
                };
            })
            .AddMicrosoftAccount(options =>
            {
                options.ClientId               = socialLogins.Microsoft.ClientId;
                options.ClientSecret           = socialLogins.Microsoft.ClientSecret;
                options.CallbackPath           = new PathString("/signin-microsoft"); // this path is used by the middleware only, no route necessary
                options.SaveTokens             = true;
                options.CorrelationCookie.Name = ".CorrAuth.League";
                options.Events.OnRemoteFailure = context =>
                {
                    // Note: If this delegate is missing, errors with the external login lead to a System.Exception: access_denied;Description=Permissions error
                    var qsParameter =
                        new Dictionary <string, string>
                    {
                        { "remoteError", context.Request.Query["error"].ToString() },
                    }.Where(item => !string.IsNullOrEmpty(item.Value)).ToDictionary(i => i.Key, i => i.Value);
                    // joins query strings from RedirectUri and qsParameter
                    var redirectUri = QueryHelpers.AddQueryString(context.Properties?.RedirectUri ?? "/", qsParameter);
                    context.Response.Redirect(redirectUri);
                    context.HandleResponse();
                    return(Task.CompletedTask);
                };
            });

            // Add before Application and External Cookie configuration and ConfigureApplicationCookie
            services.AddIdentity <ApplicationUser, ApplicationRole>(options =>
            {
                Configuration.Bind("IdentityOptions", options);     // bind to IdentityOptions section of appsettings.json
            })
            .AddDefaultTokenProviders()
            .AddUserStore <UserStore>()
            .AddRoleStore <RoleStore>()
            .AddErrorDescriber <MultiLanguageIdentityErrorDescriber>()
            .AddUserValidator <LeagueUserValidator <ApplicationUser> >();  // on top of default user validator

            // Make custom claims be added to the ClaimsPrincipal
            services.AddScoped <IUserClaimsPrincipalFactory <ApplicationUser>, LeagueClaimsPrincipalFactory>();

            // Defines the lifetime of tokens sent to users for email / password confirmation et al
            services.Configure <DataProtectionTokenProviderOptions>(options =>
                                                                    options.TokenLifespan = TimeSpan.FromDays(3)); // default: 1 day

            // Add for required user name length et al
            services.Configure <LeagueUserValidatorOptions>(Configuration.GetSection(nameof(LeagueUserValidatorOptions)));

            #endregion

            #region *** Authorization ***

            services.AddAuthorization(options =>
            {
                // Used on controller method level
                options.AddPolicy(Authorization.PolicyName.MatchPolicy, policy => policy.RequireRole(Identity.Constants.RoleName.SystemManager, Identity.Constants.RoleName.TournamentManager, Identity.Constants.RoleName.TeamManager));
                // Used in team views
                options.AddPolicy(Authorization.PolicyName.SeeTeamContactsPolicy, policy => policy.RequireRole(Identity.Constants.RoleName.SystemManager, Identity.Constants.RoleName.TournamentManager, Identity.Constants.RoleName.TeamManager, Identity.Constants.RoleName.Player));
                // Used for my team views
                options.AddPolicy(Authorization.PolicyName.MyTeamPolicy, policy => policy.RequireRole(Identity.Constants.RoleName.SystemManager, Identity.Constants.RoleName.TournamentManager, Identity.Constants.RoleName.TeamManager, Identity.Constants.RoleName.Player));
                options.AddPolicy(Authorization.PolicyName.MyTeamAdminPolicy, policy => policy.RequireRole(Identity.Constants.RoleName.SystemManager, Identity.Constants.RoleName.TournamentManager));
            });

            // Handler for match date, venue and result authorization
            services.AddSingleton <IAuthorizationHandler, Authorization.MatchAuthorizationHandler>();
            // Handler for team, team venue, team members authorization
            services.AddSingleton <IAuthorizationHandler, Authorization.TeamAuthorizationHandler>();
            // Handler for venue authorization
            services.AddSingleton <IAuthorizationHandler, Authorization.VenueAuthorizationHandler>();

            #endregion

            #region ** Application and External Cookie configuration **

            services.Configure <SecurityStampValidatorOptions>(options =>
            {
                // This determines the time span after which the validity of the authentication cookie
                // will be checked against persistent storage. It is accomplished by calling the
                // SecurityStampValidator for every request to the server. If the current time minus the
                // cookie's issue time is less or equal to ValidationInterval, a call to
                // SignInManager<TUser>.ValidateSecurityStampAsync will occur. This means ValidationInterval = TimeSpan.Zero
                // leads to calling the ValidateSecurityStampAsync for each request.
                options.ValidationInterval = TimeSpan.FromMinutes(15); // default: 30 minutes
            });

            services.ConfigureApplicationCookie(options =>
            {
                // Cookie settings
                options.Cookie.HttpOnly     = true;
                options.Cookie.IsEssential  = true;
                options.CookieManager       = new LeagueCookieManager();
                options.Cookie.Name         = ".Auth"; // will be set by LeagueCookieManager
                options.Cookie.Path         = "/";     // may be set by LeagueCookieManager
                options.LoginPath           = new PathString("/account/sign-in");
                options.LogoutPath          = new PathString("/account/sign-in");
                options.AccessDeniedPath    = new PathString("/error/access-denied");
                options.Cookie.SameSite     = Microsoft.AspNetCore.Http.SameSiteMode.Lax; // don't use Strict here
                options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
                options.ExpireTimeSpan      = TimeSpan.FromDays(30);
                options.SlidingExpiration   = true;

                options.Events.OnRedirectToAccessDenied = context =>
                {
                    var returnUrl = "?ReturnUrl=" + context.Request.Path + context.Request.QueryString;
                    // fires with [Authorize] attribute, when the user is authenticated, but does not have enough privileges
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    // other context properties can be set, but are not considered in the redirect, though
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.AccessDeniedPath) + returnUrl);
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToLogin = context =>
                {
                    var returnUrl = "?ReturnUrl=" + context.Request.Path + context.Request.QueryString;
                    // fires with [Authorize] attribute, when the user is not authenticated
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    // other context properties can be set, but are not considered in the redirect, though
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.LoginPath) + returnUrl);
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToLogout = context =>
                {
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.LogoutPath));
                    return(Task.CompletedTask);
                };
                options.Events.OnSignedIn += async context =>
                {
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    var success       = await tenantContext.DbContext.AppDb.UserRepository.SetLastLoginDateAsync(context.Principal.Identity.Name, null, CancellationToken.None);
                };
            });

            services.ConfigureExternalCookie(options =>
            {
                options.Cookie.HttpOnly    = true;
                options.Cookie.IsEssential = true;
                // MUST use the default options.CookieManager: After callback from social login, "organization" url segment will not be set,
                // because the CallbackPath from the provider will be sth. like "/signin-facebook" with cookie path to the same path.
                options.Cookie.Name       = ".ExtAuth.League";
                options.Cookie.Path       = "/";
                options.LoginPath         = new PathString("/account/sign-in");
                options.LogoutPath        = new PathString("/account/sign-in");
                options.AccessDeniedPath  = new PathString("/account/access-denied");
                options.Cookie.SameSite   = Microsoft.AspNetCore.Http.SameSiteMode.Lax; // don't use Strict here
                options.ExpireTimeSpan    = TimeSpan.FromDays(30);
                options.SlidingExpiration = true;

                options.Events.OnRedirectToAccessDenied = context =>
                {
                    var returnUrl = "?ReturnUrl=" + context.Request.Path + context.Request.QueryString;
                    // fires with [Authorize] attribute, when the user is authenticated, but does not have enough privileges
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    // other context properties can be set, but are not considered in the redirect, though
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.AccessDeniedPath) + returnUrl);
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToLogin = context =>
                {
                    var returnUrl = "?ReturnUrl=" + context.Request.Path + context.Request.QueryString;
                    // fires with [Authorize] attribute, when the user is not authenticated
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    // other context properties can be set, but are not considered in the redirect, though
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.LoginPath) + returnUrl);
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToLogout = context =>
                {
                    var tenantContext = context.HttpContext.RequestServices.GetRequiredService <ITenantContext>();
                    context.Response.Redirect(new PathString($"/{tenantContext.SiteContext.UrlSegmentValue}").Add(context.Options.LogoutPath));
                    return(Task.CompletedTask);
                };
            });

            #endregion

            #region *** MailMergeLib as a service ***

            services.AddMailMergeService(
                options =>
            {
                options.Settings = Settings.Deserialize(
                    Path.Combine(WebHostEnvironment.ContentRootPath, Program.ConfigurationFolder,
                                 $@"MailMergeLib.{WebHostEnvironment.EnvironmentName}.config"),
                    System.Text.Encoding.UTF8);
                var fms = FileMessageStore.Deserialize(Path.Combine(WebHostEnvironment.ContentRootPath, Program.ConfigurationFolder,
                                                                    "MailMergeLibMessageStore.config"), System.Text.Encoding.UTF8);
                for (var i = 0; i < fms.SearchFolders.Length; i++)
                {
                    // make relative paths absolute - ready to use
                    fms.SearchFolders[i] = Path.Combine(WebHostEnvironment.WebRootPath, fms.SearchFolders[i]);
                }
                options.MessageStore = fms;
            });

            #endregion

            #region ** Timezone service per request **

            services.AddSingleton <NodaTime.TimeZones.DateTimeZoneCache>(sp =>
                                                                         new NodaTime.TimeZones.DateTimeZoneCache(NodaTime.TimeZones.TzdbDateTimeZoneSource.Default));

            var tzId = Configuration.GetSection("TimeZone").Value ?? "America/New_York";
            // TimeZoneConverter will use the culture of the current scope
            services.AddScoped(sp => new Axuno.Tools.DateAndTime.TimeZoneConverter(
                                   sp.GetRequiredService <NodaTime.TimeZones.DateTimeZoneCache>(), tzId, CultureInfo.CurrentCulture,
                                   NodaTime.TimeZones.Resolvers.LenientResolver));

            #endregion

            #region ** Phone number service **

            services.AddSingleton <TournamentManager.DI.PhoneNumberService>(sp =>
                                                                            new PhoneNumberService(PhoneNumbers.PhoneNumberUtil.GetInstance()));

            #endregion

            services.AddSingleton <Helpers.MetaDataHelper>();

            services.Configure <CookiePolicyOptions>(options =>
            {
                // determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => false;
                options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
            });

            // expand search path to organization key sub-paths per HttpRequest
            services.Configure <RazorViewEngineOptions>(options =>
            {
                options.ViewLocationExpanders.Add(new Views.LeagueViewLocationExpander());     // R# will not resolve
                // R# will resolve: options.ViewLocationFormats.Add("/Views/Path/{0}.cshtml");
            });

            #region *** Request Localization ***

            if (bool.TryParse(Configuration.GetSection("CultureInfo:CulturePerRequest").Value, out var isCulturePerRequest) && isCulturePerRequest)
            {
                var supportedCultures = new[]
                {
                    new CultureInfo("en"),
                    new CultureInfo("de")
                };

                services.Configure <RequestLocalizationOptions>(options =>
                {
                    options.DefaultRequestCulture = new RequestCulture(CultureInfo.DefaultThreadCurrentCulture);
                    // Formatting numbers, dates, etc.
                    options.SupportedCultures = supportedCultures;
                    // UI strings that we have localized.
                    options.SupportedUICultures = supportedCultures;
                    // e.g.: "en-US" => "en"
                    options.FallBackToParentCultures   = true;
                    options.FallBackToParentUICultures = true;

                    // Select the CookieRequestCultureProvider from the default RequestCultureProviders
                    // and set another cookie name than CookieRequestCultureProvider.DefaultCookieName
                    var cookieProvider = options.RequestCultureProviders
                                         .OfType <CookieRequestCultureProvider>()
                                         .FirstOrDefault();
                    if (cookieProvider != null)
                    {
                        cookieProvider.CookieName = ".PreferredLanguage";
                    }
                });
            }

            #endregion

            services.AddRouting(options =>
            {
                options.ConstraintMap.Add(TenantRouteConstraint.Name, typeof(TenantRouteConstraint));
                options.LowercaseQueryStrings = false;     // true does not work for UrlBase64 encoded strings!
                options.LowercaseUrls         = true;
                options.AppendTrailingSlash   = false;
            }
                                );

            services.AddRazorPages().AddRazorPagesOptions(options => {  });

            var mvcBuilder = services.AddMvc(options =>
            {
                options.EnableEndpointRouting = true;
                // Add model binding messages for errors that do not reach data annotation validation
                options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueMustNotBeNull));
                options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, val) => string.Format(Resources.ModelBindingMessageResource.AttemptedValueIsInvalid, x, val));
                options.ModelBindingMessageProvider.SetValueIsInvalidAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueIsInvalid, x));
                options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueMustBeANumber, x));
                options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => Resources.ModelBindingMessageResource.MissingKeyOrValue);
            })
                             .SetCompatibilityVersion(CompatibilityVersion.Latest)
                             .AddSessionStateTempDataProvider()
                             .AddDataAnnotationsLocalization()
                             .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                             .AddMvcOptions(options =>
            {
                // Insert custom model binder providers before SimpleTypeModelBinderProvider
                options.ModelBinderProviders.Insert(0, new TimeSpanModelBinderProvider());
                options.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider());
                // Replace ComplexTypeModelBinder with TrimmingModelBinder (trims all strings in models)
                options.ModelBinderProviders[options.ModelBinderProviders.TakeWhile(p => !(p is Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinderProvider)).Count()] = new ModelBinders.TrimmingComplexModelBinderProvider();
            })
                             .AddControllersAsServices(); // will add controllers with ServiceLifetime.Transient
#if DEBUG
            // Not to be added in production!
            if (WebHostEnvironment.IsDevelopment())
            {
                mvcBuilder.AddRazorRuntimeCompilation();
            }
#endif
            services.AddHttpsRedirection(options =>
            {
                options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
            });

            #region *** Add CloudScribeNavigation ***

            // CloudscribeNavigation requires:
            // ~/Views/Shared/NavigationNodeChildDropdownPartial.cshtml
            // ~/Views/Shared/NavigationNodeChildTreePartial.cshtml
            // ~/Views/Shared/NavigationNodeSideNavPartial.cshtml
            // ~/Views/Shared/Components/Navigation/*.cshtml
            // ~/Views/_ViewImports.cshtml: @using cloudscribe.Web.Navigation

            //services.AddCloudscribeNavigation(Configuration.GetSection("NavigationOptions"));
            services.AddCloudscribeNavigation(null);
            services.AddScoped <IOptions <NavigationOptions>, Navigation.LeagueSiteNavigationOptionsResolver>(); // resolve navigation xml files per organization
            services.AddScoped <INavigationTreeBuilder, Navigation.HomeNavigationTreeBuilder>();                 //add top nav home button per tenant
            services.AddScoped <INavigationTreeBuilder, Navigation.LeaguesNavigationTreeBuilder>();              //add top nav item for leagues per tenant
            services.AddScoped <INavigationTreeBuilder, Navigation.InfosNavigationTreeBuilder>();                //add top nav item for info menu per tenant
            services.AddScoped <ITreeCache, Navigation.LeagueMemoryTreeCache>();                                 // cache navigation tree per tenant
            #endregion

            #region *** Text Templating ***

            services.AddTextTemplatingModule(vfs =>
            {
                // The complete Templates folder is embedded in the project file
                vfs.FileSets.AddEmbedded <Startup>(nameof(League) + ".Templates");
                // vfs.FileSets.AddPhysical(Path.Combine(Directory.GetCurrentDirectory(), "Templates"));
            },
                                             locOpt =>
            {
            },
                                             renderOptions =>
            {
#if DEBUG
                renderOptions.MemberNotFoundAction   = RenderErrorAction.ThrowError;
                renderOptions.VariableNotFoundAction = RenderErrorAction.ThrowError;
#else
                renderOptions.MemberNotFoundAction   = RenderErrorAction.MaintainToken;
                renderOptions.VariableNotFoundAction = RenderErrorAction.MaintainToken;
#endif
            });

            #endregion

            #region *** HostedServices related ***

            // RazorViewToStringRenderer must be used with the current HttpContext
            // Note: RazorViewToStringRenderer is currently only used for MatchReport
            services.AddTransient <RazorViewToStringRenderer>();
            services.Configure <BackgroundQueueConfig>(config => config.OnException = null);
            services.AddSingleton <IBackgroundQueue, BackgroundQueue>();
            services.AddConcurrentBackgroundQueueService();
            services.AddTransient <SendEmailTask>();
            services.AddTransient <RankingUpdateTask>();

            #endregion
        }
예제 #30
0
        // 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)
        {
            // required for cookies and session cookies (will throw CryptographicException without)
            services.AddDataProtection()
            .SetApplicationName("ClubSite")
            .SetDefaultKeyLifetime(TimeSpan.FromDays(360))
            .PersistKeysToFileSystem(
                new DirectoryInfo(Path.Combine(WebHostEnvironment.ContentRootPath, "DataProtectionKeys")))
            .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration()
            {
                EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
                ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
            });

            // Make sure we can connect to the database
            using (var connection =
                       new Microsoft.Data.SqlClient.SqlConnection(Configuration.GetConnectionString("VolleyballClub")))
                try
                {
                    connection.Open();
                }
                finally
                {
                    connection.Close();
                }

            services.AddMemoryCache(); // Adds a default in-memory cache implementation

            // Custom ClubSite db context
            services.AddDbContext <Data.ClubDbContext>((sp, options) =>
                                                       options.UseSqlServer(Configuration.GetConnectionString("VolleyballClub")));

            // Piranha service setup
            services.AddPiranha(svcBuilder =>
            {
                svcBuilder.AddRazorRuntimeCompilation = WebHostEnvironment.IsDevelopment();

                svcBuilder.UseCms();
                svcBuilder.UseFileStorage(naming: Piranha.Local.FileStorageNaming.UniqueFolderNames);
                svcBuilder.UseImageSharp();
                svcBuilder.UseManager(); // https://localhost:44306/manager/ initial user: admin, pw: password
                svcBuilder.UseTinyMCE();
                svcBuilder.UseMemoryCache();
                svcBuilder.UseEF <SQLServerDb>(db =>
                                               db.UseSqlServer(Configuration.GetConnectionString("VolleyballClub")));
                svcBuilder.UseIdentityWithSeed <IdentitySQLServerDb>(db =>
                                                                     db.UseSqlServer(Configuration.GetConnectionString("VolleyballClub")));
            });

            // MUST be before AddMvc!
            services.AddSession(options =>
            {
                options.IdleTimeout        = TimeSpan.FromMinutes(60);
                options.Cookie.HttpOnly    = true;
                options.Cookie.Name        = ".sid";
                options.Cookie.IsEssential = true;
            });

            services.AddRazorPages().AddPiranhaManagerOptions();

            services.AddMvc()
            .AddSessionStateTempDataProvider()
            .AddMvcOptions(options =>
            {
                options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueMustNotBeNull));
                options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, val) => string.Format(Resources.ModelBindingMessageResource.AttemptedValueIsInvalid, x, val));
                options.ModelBindingMessageProvider.SetValueIsInvalidAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueIsInvalid, x));
                options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(x => string.Format(Resources.ModelBindingMessageResource.ValueMustBeANumber, x));
                options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => Resources.ModelBindingMessageResource.MissingKeyOrValue);
            })
            .AddControllersAsServices();

            services.AddHttpsRedirection(options =>
            {
                options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
            });

            services.Configure <ConfigurationPoco.MailSettings>(
                Configuration.GetSection(nameof(ConfigurationPoco.MailSettings)) ??
                throw new ArgumentNullException(
                    $"Configuration section '{nameof(ConfigurationPoco.MailSettings)}' not found."));

            services.AddTransient <Services.IMailService, Services.MailService>();
        }