예제 #1
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();
            });
        }
예제 #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 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!");
                });
            });
        }
예제 #4
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddInfrastructure(WebHostEnvironment.IsDevelopment());
            services.AddPersistence(Configuration);
            services.AddApplication();

            services.AddControllers();

            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });
        }
예제 #5
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();
            });
        }
예제 #6
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")));
            }
        }
예제 #7
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());
        }
예제 #8
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
        }
예제 #9
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());
        }
예제 #10
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
        }
예제 #11
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>();
        }
예제 #12
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>();
        }
예제 #13
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?}");
            });
        }
예제 #14
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>();
        }
예제 #15
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
        }
예제 #16
0
        /// <summary>
        /// 注入服务
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure <CoreWebSite>(Configuration.GetSection("CoreWebSite"));
            services.Configure <CoreUpload>(Configuration.GetSection("CoreUpload"));
            services.AddCommonService()
            .AddRepositoryService()
            .AddDomainService();
            var assmebies = new System.IO.DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).GetFiles("Core.Application*.dll")
                            .Select(x => System.Reflection.Assembly.LoadFrom(x.FullName)).ToArray();

            services.AddMvc(option =>
            {
            }).AddApplicationPart(assmebies.FirstOrDefault())
            .AddRazorOptions(options =>
            {
                options.AreaViewLocationFormats.Add("/Core/Admin/{1}/{0}.cshtml");
                options.AreaViewLocationFormats.Add("/Core/Admin/{0}.cshtml");
                options.AreaViewLocationFormats.Add("/Core/Admin/Shared/{0}.cshtml");

                options.ViewLocationFormats.Add("/Core/Mobile/{1}/{0}.cshtml");
                options.ViewLocationFormats.Add("/Core/Mobile/{0}.cshtml");
                options.ViewLocationFormats.Add("/Core/Mobile/Shared/{0}.cshtml");
            }).AddJsonOptions(option =>
            {
                option.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
            });
            services.AddDbContext <BaseDbContext>(option =>
            {
                var connectionString = Configuration.GetConnectionString("Core");
                option.UseSqlServer(connectionString, b => b.UseRowNumberForPaging());//分页增加对sqlserver2008的支持
                var logFactory = new LoggerFactory();
                logFactory.AddLog4Net();
                option.UseLoggerFactory(logFactory);                         //添加sql监控日志
            });                                                              //初始化数据库连接
            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //添加对象映射组件
            services.AddHttpContextAccessor();
            services.AddAuthentication(option =>
            {
                option.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                option.RequireAuthenticatedSignIn = false;
            }).AddCookie(option =>
            {
                option.LoginPath          = "/User/Login";
                option.LogoutPath         = "/User/LoginOut";
                option.Events.OnSigningIn = (context) =>
                {
                    var cookieName = context.Options.Cookie.Name;
                    return(Task.CompletedTask);
                };
            });
            services.AddSession();
            if (WebHostEnvironment.IsDevelopment())
            {
                services.AddMemoryCache();
            }
            else
            {
                services.AddDistributedRedisCache(option =>
                {
                    option.Configuration = "127.0.0.1";
                    option.InstanceName  = "db0";
                });
            }
            services.AddUEditorService();
            services.AddDapper("sqlserver", option =>
            {
                option.ConnectionString = Configuration.GetConnectionString("Core");
                option.DBType           = CoreEnum.DBType.SqlServer;
            });
            ServiceCollection = services;
        }