Exemplo n.º 1
0
 public HangfireLauncher(HangfireOptions options)
 {
     _options = options;
 }
Exemplo n.º 2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            // This custom provider allows able to use just [Authorize] instead of having to define [Authorize(AuthenticationSchemes = "Bearer")] above every API controller
            // without this Bearer authorization will not work
            services.AddSingleton <IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();

            services.Configure <PlatformOptions>(Configuration.GetSection("VirtoCommerce"));
            services.Configure <HangfireOptions>(Configuration.GetSection("VirtoCommerce:Jobs"));

            PlatformVersion.CurrentVersion = SemanticVersion.Parse(Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.ApplicationVersion);

            services.AddPlatformServices(Configuration);
            services.AddSecurityServices();

            var mvcBuilder = services.AddMvc(mvcOptions =>
            {
                // NOTE: combining multiple Authorize attributes when using a custom IAuthorizationPolicyProvider
                //       with ASP.NET Core MVC 2.1 causes an ArgumentNullException when calling an action.
                //       For more information, please see https://github.com/aspnet/Mvc/issues/7809
                //
                // Currently this issue affects following controllers:
                // - VirtoCommerce.Platform.Web.Controllers.Api.DynamicPropertiesController
                // - VirtoCommerce.SitemapsModule.Web.Controllers.Api.SitemapsModuleApiController
                // - probably some other controllers in modules not ported to VC Platform 3.x yet...
                //
                // This issue is fixed in ASP.NET Core MVC 2.2. The following line is a workaround for 2.1.
                // TODO: remove the following workaround after migrating to ASP.NET Core MVC 2.2
                mvcOptions.AllowCombiningAuthorizeFilters = false;
            }
                                             )
                             .AddJsonOptions(options =>
            {
                //Next line needs to represent custom derived types in the resulting swagger doc definitions. Because default SwaggerProvider used global JSON serialization settings
                //we should register this converter globally.
                options.SerializerSettings.ContractResolver = new PolymorphJsonContractResolver();
                //Next line allow to use polymorph types as parameters in API controller methods
                options.SerializerSettings.Converters.Add(new PolymorphJsonConverter());
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateTimeZoneHandling  = DateTimeZoneHandling.Utc;
                options.SerializerSettings.NullValueHandling     = NullValueHandling.Ignore;
                options.SerializerSettings.Converters.Add(new StringEnumConverter());
                options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
                options.SerializerSettings.Formatting = Formatting.None;

                options.SerializerSettings.Error += (sender, args) =>
                {
                    // Expose any JSON serialization exception as HTTP error
                    throw new JsonException(args.ErrorContext.Error.Message);
                };
                options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            }
                                             )
                             .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            var modulesDiscoveryPath = Path.GetFullPath("Modules");

            services.AddModules(mvcBuilder, options =>
            {
                options.DiscoveryPath = modulesDiscoveryPath;
                options.ProbingPath   = "App_Data/Modules";
            });

            services.Configure <ExternalModuleCatalogOptions>(Configuration.GetSection("ExternalModules"));
            services.AddExternalModules();

            services.AddDbContext <SecurityDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("VirtoCommerce"));
                // Register the entity sets needed by OpenIddict.
                // Note: use the generic overload if you need
                // to replace the default OpenIddict entities.
                options.UseOpenIddict();
            });

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

            services.AddSecurityServices(options =>
            {
                options.NonEditableUsers = new[] { "admin" };
            });

            services.AddIdentity <ApplicationUser, Role>()
            .AddEntityFrameworkStores <SecurityDbContext>()
            .AddDefaultTokenProviders();

            // Configure Identity to use the same JWT claims as OpenIddict instead
            // of the legacy WS-Federation claims it uses by default (ClaimTypes),
            // which saves you from doing the mapping in your authorization controller.
            services.Configure <IdentityOptions>(options =>
            {
                options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Subject;
                options.ClaimsIdentity.UserIdClaimType   = OpenIdConnectConstants.Claims.Name;
                options.ClaimsIdentity.RoleClaimType     = OpenIdConnectConstants.Claims.Role;
            });

            services.Configure <Core.Security.AuthorizationOptions>(Configuration.GetSection("Authorization"));
            var authorizationOptions = Configuration.GetSection("Authorization").Get <Core.Security.AuthorizationOptions>();

            // Register the OpenIddict services.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            services.AddOpenIddict()
            .AddCore(options =>
            {
                options.UseEntityFrameworkCore()
                .UseDbContext <SecurityDbContext>();
            }).AddServer(options =>
            {
                // Register the ASP.NET Core MVC binder used by OpenIddict.
                // Note: if you don't call this method, you won't be able to
                // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
                options.UseMvc();

                // Enable the authorization, logout, token and userinfo endpoints.
                options.EnableTokenEndpoint("/connect/token")
                .EnableUserinfoEndpoint("/api/security/userinfo");

                // Note: the Mvc.Client sample only uses the code flow and the password flow, but you
                // can enable the other flows if you need to support implicit or client credentials.
                options.AllowPasswordFlow()
                .AllowRefreshTokenFlow();

                options.SetRefreshTokenLifetime(authorizationOptions.RefreshTokenLifeTime);
                options.SetAccessTokenLifetime(authorizationOptions.AccessTokenLifeTime);

                options.AcceptAnonymousClients();

                // Configure Openiddict to issues new refresh token for each token refresh request.
                options.UseRollingTokens();

                // Make the "client_id" parameter mandatory when sending a token request.
                //options.RequireClientIdentification();

                // When request caching is enabled, authorization and logout requests
                // are stored in the distributed cache by OpenIddict and the user agent
                // is redirected to the same page with a single parameter (request_id).
                // This allows flowing large OpenID Connect requests even when using
                // an external authentication provider like Google, Facebook or Twitter.
                options.EnableRequestCaching();

                options.UseReferenceTokens();
                options.DisableScopeValidation();

                // During development, you can disable the HTTPS requirement.
                if (HostingEnvironment.IsDevelopment())
                {
                    options.DisableHttpsRequirement();
                }

                // Note: to use JWT access tokens instead of the default
                // encrypted format, the following lines are required:
                //
                //options.UseJsonWebTokens();
                //TODO: Replace to X.509 certificate
                //options.AddEphemeralSigningKey();
            }).AddValidation(options => options.UseReferenceTokens());

            services.Configure <IdentityOptions>(Configuration.GetSection("IdentityOptions"));

            //always  return 401 instead of 302 for unauthorized  requests
            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return(Task.CompletedTask);
                };
            });

            services.AddAuthorization();
            // register the AuthorizationPolicyProvider which dynamically registers authorization policies for each permission defined in module manifest
            services.AddSingleton <IAuthorizationPolicyProvider, PermissionAuthorizationPolicyProvider>();
            //Platform authorization handler for policies based on permissions
            services.AddSingleton <IAuthorizationHandler, PermissionAuthorizationHandler>();

            // Add memory cache services
            services.AddMemoryCache();

            // Register the Swagger generator
            services.AddSwagger();

            //Add SignalR for push notifications
            services.AddSignalR();


            var assetsProvider = Configuration.GetSection("Assets:Provider").Value;

            if (assetsProvider.EqualsInvariant(AzureBlobProvider.ProviderName))
            {
                services.Configure <AzureBlobContentOptions>(Configuration.GetSection("Assets:AzureBlobStorage"));
                services.AddAzureBlobProvider();
            }
            else
            {
                services.Configure <FileSystemBlobContentOptions>(Configuration.GetSection("Assets:FileSystem"));
                services.AddFileSystemBlobProvider(options =>
                {
                    options.RootPath = HostingEnvironment.MapPath(options.RootPath);
                });
            }

            var hangfireOptions = new HangfireOptions();

            Configuration.GetSection("VirtoCommerce:Hangfire").Bind(hangfireOptions);
            if (hangfireOptions.JobStorageType == HangfireJobStorageType.SqlServer)
            {
                services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("VirtoCommerce")));
            }
            else
            {
                services.AddHangfire(config => config.UseMemoryStorage());
            }
        }
Exemplo n.º 3
0
        public void Configuration(IAppBuilder app, string virtualRoot, string routPrefix)
        {
            VirtualRoot = virtualRoot;

            _assembliesPath = HostingEnvironment.MapPath(VirtualRoot + "/App_Data/Modules");
            var platformPath        = HostingEnvironment.MapPath(VirtualRoot).EnsureEndSeparator();
            var modulesVirtualPath  = VirtualRoot + "/Modules";
            var modulesPhysicalPath = HostingEnvironment.MapPath(modulesVirtualPath).EnsureEndSeparator();

            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;

            //Modules initialization
            var bootstrapper = new PremierSoftBarWebBootstrapper(modulesVirtualPath, modulesPhysicalPath, _assembliesPath, platformPath);

            bootstrapper.Run();

            var container = bootstrapper.Container;

            container.RegisterInstance(app);

            var moduleInitializerOptions = (ModuleInitializerOptions)container.Resolve <IModuleInitializerOptions>();

            moduleInitializerOptions.VirtualRoot = virtualRoot;
            moduleInitializerOptions.RoutePrefix = routPrefix;

            //Initialize Platform dependencies
            const string connectionStringName = "BarEntities";

            var hangfireOptions = new HangfireOptions
            {
                StartServer    = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Jobs.Enabled", true),
                JobStorageType = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Jobs.StorageType", "Memory"),
                DatabaseConnectionStringName = connectionStringName,
            };
            var hangfireLauncher = new HangfireLauncher(hangfireOptions);

            InitializePlatform(app, container, connectionStringName, hangfireLauncher);

            var moduleManager = container.Resolve <IModuleManager>();
            var moduleCatalog = container.Resolve <IModuleCatalog>();


            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.EnsureEndSeparator();

            // Register URL rewriter for platform scripts
            var scriptsPhysicalPath        = HostingEnvironment.MapPath(VirtualRoot + "/Scripts").EnsureEndSeparator();
            var scriptsRelativePath        = MakeRelativePath(applicationBase, scriptsPhysicalPath);
            var platformUrlRewriterOptions = new UrlRewriterOptions();

            platformUrlRewriterOptions.Items.Add(PathString.FromUriComponent("/$(Platform)/Scripts"), "");
            app.Use <UrlRewriterOwinMiddleware>(platformUrlRewriterOptions);
            app.UseStaticFiles(new StaticFileOptions
            {
                FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(scriptsRelativePath)
            });

            // Register URL rewriter before modules initialization
            if (Directory.Exists(modulesPhysicalPath))
            {
                var modulesRelativePath = MakeRelativePath(applicationBase, modulesPhysicalPath);

                var urlRewriterOptions = new UrlRewriterOptions();

                foreach (var module in moduleCatalog.Modules.OfType <ManifestModuleInfo>())
                {
                    var urlRewriteKey   = string.Format(CultureInfo.InvariantCulture, "/Modules/$({0})", module.ModuleName);
                    var urlRewriteValue = MakeRelativePath(modulesPhysicalPath, module.FullPhysicalPath);
                    urlRewriterOptions.Items.Add(PathString.FromUriComponent(urlRewriteKey), "/" + urlRewriteValue);

                    moduleInitializerOptions.ModuleDirectories.Add(module.ModuleName, module.FullPhysicalPath);
                }

                app.Use <UrlRewriterOwinMiddleware>(urlRewriterOptions);
                app.UseStaticFiles(new StaticFileOptions
                {
                    FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(modulesRelativePath)
                });
            }

            container.RegisterInstance(GlobalConfiguration.Configuration);

            // Ensure all modules are loaded
            foreach (var module in moduleCatalog.Modules.Where(x => x.State == ModuleState.NotStarted))
            {
                moduleManager.LoadModule(module.ModuleName);
            }

            SwaggerConfig.RegisterRoutes(container);

            // Post-initialize

            // Platform MVC configuration
            if (IsApplication)
            {
                AreaRegistration.RegisterAllAreas();
            }

            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Security OWIN configuration
            var authenticationOptions = new VirtoCommerce.Platform.Core.Security.AuthenticationOptions
            {
                CookiesEnabled             = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Cookies.Enabled", true),
                CookiesValidateInterval    = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Cookies.ValidateInterval", TimeSpan.FromDays(1)),
                BearerTokensEnabled        = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:BearerTokens.Enabled", true),
                BearerTokensExpireTimeSpan = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:BearerTokens.AccessTokenExpireTimeSpan", TimeSpan.FromHours(1)),
                HmacEnabled = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Hmac.Enabled", true),
                HmacSignatureValidityPeriod = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Hmac.SignatureValidityPeriod", TimeSpan.FromMinutes(20)),
                ApiKeysEnabled                  = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.Enabled", true),
                ApiKeysHttpHeaderName           = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.HttpHeaderName", "api_key"),
                ApiKeysQueryStringParameterName = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.QueryStringParameterName", "api_key"),
            };

            OwinConfig.Configure(app, container, authenticationOptions);

            hangfireLauncher.ConfigureOwin(app, container);

            RecurringJob.AddOrUpdate <SendNotificationsJobs>("SendNotificationsJob", x => x.Process(), "*/1 * * * *");

            var notificationManager = container.Resolve <INotificationManager>();

            notificationManager.RegisterNotificationType(() => new RegistrationEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Registration notification",
                Description          = "This notification sends by email to client when he finish registration",
                NotificationTemplate = new NotificationTemplate
                {
                    Body    = PlatformNotificationResource.RegistrationNotificationBody,
                    Subject = PlatformNotificationResource.RegistrationNotificationSubject,
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Reset password notification",
                Description          = "This notification sends by email to client when he want to reset his password",
                NotificationTemplate = new NotificationTemplate
                {
                    Body    = PlatformNotificationResource.ResetPasswordNotificationBody,
                    Subject = PlatformNotificationResource.ResetPasswordNotificationSubject,
                }
            });

            var postInitializeModules = moduleCatalog.CompleteListWithDependencies(moduleCatalog.Modules)
                                        .Where(m => m.ModuleInstance != null)
                                        .ToArray();

            foreach (var module in postInitializeModules)
            {
                moduleManager.PostInitializeModule(module);
            }

            // SignalR
            var tempCounterManager = new TempPerformanceCounterManager();

            GlobalHost.DependencyResolver.Register(typeof(IPerformanceCounterManager), () => tempCounterManager);
            var hubConfiguration = new HubConfiguration {
                EnableJavaScriptProxies = false
            };

            app.MapSignalR("/" + moduleInitializerOptions.RoutePrefix + "signalr", hubConfiguration);

            // Initialize InstrumentationKey from EnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY")
            var appInsightKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");

            if (!string.IsNullOrEmpty(appInsightKey))
            {
                TelemetryConfiguration.Active.InstrumentationKey = appInsightKey;
            }
        }
Exemplo n.º 4
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            // This custom provider allows able to use just [Authorize] instead of having to define [Authorize(AuthenticationSchemes = "Bearer")] above every API controller
            // without this Bearer authorization will not work
            services.AddSingleton <IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();

            services.AddSingleton <IPushNotificationManager, PushNotificationManager>();

            services.AddOptions <PlatformOptions>().Bind(Configuration.GetSection("VirtoCommerce")).ValidateDataAnnotations();
            services.AddOptions <HangfireOptions>().Bind(Configuration.GetSection("VirtoCommerce:Hangfire")).ValidateDataAnnotations();
            services.AddOptions <TranslationOptions>().Configure(options =>
            {
                options.PlatformTranslationFolderPath = WebHostEnvironment.MapPath(options.PlatformTranslationFolderPath);
            });
            //Get platform version from GetExecutingAssembly
            PlatformVersion.CurrentVersion = SemanticVersion.Parse(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion);

            services.AddPlatformServices(Configuration);
            services.AddSecurityServices();
            services.AddSingleton <LicenseProvider>();

            // The following line enables Application Insights telemetry collection.
            services.AddApplicationInsightsTelemetry();
            services.AddApplicationInsightsTelemetryProcessor <IgnoreSignalRTelemetryProcessor>();

            var mvcBuilder = services.AddMvc(mvcOptions =>
            {
                //Disable 204 response for null result. https://github.com/aspnet/AspNetCore/issues/8847
                var noContentFormatter = mvcOptions.OutputFormatters.OfType <HttpNoContentOutputFormatter>().FirstOrDefault();
                if (noContentFormatter != null)
                {
                    noContentFormatter.TreatNullValueAsNoContent = false;
                }
            }
                                             )
                             .AddNewtonsoftJson(options =>
            {
                //Next line needs to represent custom derived types in the resulting swagger doc definitions. Because default SwaggerProvider used global JSON serialization settings
                //we should register this converter globally.
                options.SerializerSettings.ContractResolver = new PolymorphJsonContractResolver();
                //Next line allow to use polymorph types as parameters in API controller methods
                options.SerializerSettings.Converters.Add(new PolymorphJsonConverter());
                options.SerializerSettings.Converters.Add(new ModuleIdentityJsonConverter());
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateTimeZoneHandling  = DateTimeZoneHandling.Utc;
                options.SerializerSettings.NullValueHandling     = NullValueHandling.Ignore;
                options.SerializerSettings.Converters.Add(new StringEnumConverter());
                options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
                options.SerializerSettings.Formatting = Formatting.None;

                options.SerializerSettings.Error += (sender, args) =>
                {
                    // Expose any JSON serialization exception as HTTP error
                    throw new JsonException(args.ErrorContext.Error.Message);
                };
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            }
                                                );

            services.AddSingleton(js =>
            {
                var serv = js.GetService <IOptions <MvcNewtonsoftJsonOptions> >();
                return(JsonSerializer.Create(serv.Value.SerializerSettings));
            });

            services.AddDbContext <SecurityDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("VirtoCommerce"));
                // Register the entity sets needed by OpenIddict.
                // Note: use the generic overload if you need
                // to replace the default OpenIddict entities.
                options.UseOpenIddict();
            });

            // Enable synchronous IO if using Kestrel:
            services.Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // Enable synchronous IO if using IIS:
            services.Configure <IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

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

            var authBuilder = services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                              //Add the second ApiKey auth schema to handle api_key in query string
                              .AddScheme <ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options => { })
                              .AddCookie();


            services.AddSecurityServices(options =>
            {
                options.NonEditableUsers = new[] { "admin" };
            });

            services.AddIdentity <ApplicationUser, Role>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores <SecurityDbContext>()
            .AddDefaultTokenProviders();

            // Configure Identity to use the same JWT claims as OpenIddict instead
            // of the legacy WS-Federation claims it uses by default (ClaimTypes),
            // which saves you from doing the mapping in your authorization controller.
            services.Configure <IdentityOptions>(options =>
            {
                options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Subject;
                options.ClaimsIdentity.UserIdClaimType   = OpenIdConnectConstants.Claims.Name;
                options.ClaimsIdentity.RoleClaimType     = OpenIdConnectConstants.Claims.Role;
            });

            // Support commonly used forwarded headers
            // X-Forwarded-For - Holds Client IP (optionally port number) across proxies and ends up in HttpContext.Connection.RemoteIpAddress
            // X-Forwarded-Proto - Holds original scheme (HTTP or HTTPS) even if call traversed proxies and changed and ends up in HttpContext.Request.Scheme
            services.Configure <ForwardedHeadersOptions>(options =>
            {
                options.KnownProxies.Clear();
                options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor;
            });

            //Create backup of token handler before default claim maps are cleared
            var defaultTokenHandler = new JwtSecurityTokenHandler();

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
            authBuilder.AddJwtBearer(options =>
            {
                options.Authority = Configuration["Auth:Authority"];
                options.Audience  = Configuration["Auth:Audience"];

                if (WebHostEnvironment.IsDevelopment())
                {
                    options.RequireHttpsMetadata = false;
                }

                options.IncludeErrorDetails = true;

                X509SecurityKey publicKey = null;
                if (!Configuration["Auth:PublicCertPath"].IsNullOrEmpty())
                {
                    var publicCert = new X509Certificate2(Configuration["Auth:PublicCertPath"]);
                    publicKey      = new X509SecurityKey(publicCert);
                }

                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    NameClaimType            = OpenIdConnectConstants.Claims.Subject,
                    RoleClaimType            = OpenIdConnectConstants.Claims.Role,
                    ValidateIssuer           = !string.IsNullOrEmpty(options.Authority),
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey         = publicKey
                };
            });

            var azureAdSection = Configuration.GetSection("AzureAd");

            if (azureAdSection.GetChildren().Any())
            {
                var options = new AzureAdOptions();
                azureAdSection.Bind(options);

                if (options.Enabled)
                {
                    //TODO: Need to check how this influence to OpennIddict Reference tokens activated by this line below  AddValidation(options => options.UseReferenceTokens());
                    authBuilder.AddOpenIdConnect(options.AuthenticationType, options.AuthenticationCaption,
                                                 openIdConnectOptions =>
                    {
                        openIdConnectOptions.ClientId               = options.ApplicationId;
                        openIdConnectOptions.Authority              = $"{options.AzureAdInstance}{options.TenantId}";
                        openIdConnectOptions.UseTokenLifetime       = true;
                        openIdConnectOptions.RequireHttpsMetadata   = false;
                        openIdConnectOptions.SignInScheme           = IdentityConstants.ExternalScheme;
                        openIdConnectOptions.SecurityTokenValidator = defaultTokenHandler;
                    });
                }
            }

            services.AddOptions <Core.Security.AuthorizationOptions>().Bind(Configuration.GetSection("Authorization")).ValidateDataAnnotations();
            var authorizationOptions = Configuration.GetSection("Authorization").Get <Core.Security.AuthorizationOptions>();
            var platformOptions      = Configuration.GetSection("VirtoCommerce").Get <PlatformOptions>();

            // Register the OpenIddict services.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            services.AddOpenIddict()
            .AddCore(options =>
            {
                options.UseEntityFrameworkCore()
                .UseDbContext <SecurityDbContext>();
            }).AddServer(options =>
            {
                // Register the ASP.NET Core MVC binder used by OpenIddict.
                // Note: if you don't call this method, you won't be able to
                // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
                options.UseMvc();

                // Enable the authorization, logout, token and userinfo endpoints.
                options.EnableTokenEndpoint("/connect/token")
                .EnableUserinfoEndpoint("/api/security/userinfo");

                // Note: the Mvc.Client sample only uses the code flow and the password flow, but you
                // can enable the other flows if you need to support implicit or client credentials.
                options.AllowPasswordFlow()
                .AllowRefreshTokenFlow()
                .AllowClientCredentialsFlow();

                options.SetRefreshTokenLifetime(authorizationOptions?.RefreshTokenLifeTime);
                options.SetAccessTokenLifetime(authorizationOptions?.AccessTokenLifeTime);

                options.AcceptAnonymousClients();

                // Configure Openiddict to issues new refresh token for each token refresh request.
                options.UseRollingTokens();

                // Make the "client_id" parameter mandatory when sending a token request.
                //options.RequireClientIdentification();

                // When request caching is enabled, authorization and logout requests
                // are stored in the distributed cache by OpenIddict and the user agent
                // is redirected to the same page with a single parameter (request_id).
                // This allows flowing large OpenID Connect requests even when using
                // an external authentication provider like Google, Facebook or Twitter.
                options.EnableRequestCaching();

                options.DisableScopeValidation();

                // During development or when you explicitly run the platform in production mode without https, need to disable the HTTPS requirement.
                if (WebHostEnvironment.IsDevelopment() || platformOptions.AllowInsecureHttp || !Configuration.IsHttpsServerUrlSet())
                {
                    options.DisableHttpsRequirement();
                }

                // Note: to use JWT access tokens instead of the default
                // encrypted format, the following lines are required:
                options.UseJsonWebTokens();

                var bytes = File.ReadAllBytes(Configuration["Auth:PrivateKeyPath"]);
                X509Certificate2 privateKey;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    // https://github.com/dotnet/corefx/blob/release/2.2/Documentation/architecture/cross-platform-cryptography.md
                    // macOS cannot load certificate private keys without a keychain object, which requires writing to disk. Keychains are created automatically for PFX loading, and are deleted when no longer in use. Since the X509KeyStorageFlags.EphemeralKeySet option means that the private key should not be written to disk, asserting that flag on macOS results in a PlatformNotSupportedException.
                    privateKey = new X509Certificate2(bytes, Configuration["Auth:PrivateKeyPassword"], X509KeyStorageFlags.MachineKeySet);
                }
                else
                {
                    privateKey = new X509Certificate2(bytes, Configuration["Auth:PrivateKeyPassword"], X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet);
                }
                options.AddSigningCertificate(privateKey);
            });

            services.Configure <IdentityOptions>(Configuration.GetSection("IdentityOptions"));

            //always  return 401 instead of 302 for unauthorized  requests
            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return(Task.CompletedTask);
                };
            });

            services.AddAuthorization(options =>
            {
                //We need this policy because it is a single way to implicitly use the two schema (JwtBearer and ApiKey)  authentication for resource based authorization.
                var mutipleSchemaAuthPolicy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme, ApiKeyAuthenticationOptions.DefaultScheme)
                                              .RequireAuthenticatedUser()
                                              .Build();
                //The good article is described the meaning DefaultPolicy and FallbackPolicy
                //https://scottsauber.com/2020/01/20/globally-require-authenticated-users-by-default-using-fallback-policies-in-asp-net-core/
                options.DefaultPolicy = mutipleSchemaAuthPolicy;
            });
            // register the AuthorizationPolicyProvider which dynamically registers authorization policies for each permission defined in module manifest
            services.AddSingleton <IAuthorizationPolicyProvider, PermissionAuthorizationPolicyProvider>();
            //Platform authorization handler for policies based on permissions
            services.AddSingleton <IAuthorizationHandler, DefaultPermissionAuthorizationHandler>();
            // Default password validation service implementation
            services.AddScoped <IPasswordCheckService, PasswordCheckService>();

            services.AddOptions <LocalStorageModuleCatalogOptions>().Bind(Configuration.GetSection("VirtoCommerce"))
            .PostConfigure(options =>
            {
                options.DiscoveryPath = Path.GetFullPath(options.DiscoveryPath ?? "Modules");
            })
            .ValidateDataAnnotations();
            services.AddModules(mvcBuilder);

            services.AddOptions <ExternalModuleCatalogOptions>().Bind(Configuration.GetSection("ExternalModules")).ValidateDataAnnotations();
            services.AddExternalModules();

            //Add SignalR for push notifications
            services.AddSignalR();

            var assetsProvider = Configuration.GetSection("Assets:Provider").Value;

            if (assetsProvider.EqualsInvariant(AzureBlobProvider.ProviderName))
            {
                services.AddOptions <AzureBlobOptions>().Bind(Configuration.GetSection("Assets:AzureBlobStorage")).ValidateDataAnnotations();
                services.AddAzureBlobProvider();
            }
            else
            {
                services.AddOptions <FileSystemBlobOptions>().Bind(Configuration.GetSection("Assets:FileSystem"))
                .PostConfigure(options =>
                {
                    options.RootPath = WebHostEnvironment.MapPath(options.RootPath);
                }).ValidateDataAnnotations();

                services.AddFileSystemBlobProvider();
            }

            var hangfireOptions = new HangfireOptions();

            Configuration.GetSection("VirtoCommerce:Hangfire").Bind(hangfireOptions);

            GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute {
                Attempts = hangfireOptions.AutomaticRetryCount
            });
            if (hangfireOptions.JobStorageType == HangfireJobStorageType.SqlServer)
            {
                services.AddHangfire(configuration => configuration.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                                     .UseSimpleAssemblyNameTypeSerializer()
                                     .UseRecommendedSerializerSettings()
                                     .UseSqlServerStorage(Configuration.GetConnectionString("VirtoCommerce"), hangfireOptions.SqlServerStorageOptions));
            }
            else
            {
                services.AddHangfire(config => config.UseMemoryStorage());
            }
            //Conditionally use the hangFire server for this app instance to have possibility to disable processing background jobs
            if (hangfireOptions.UseHangfireServer)
            {
                services.AddHangfireServer();
            }
            // Register the Swagger generator
            services.AddSwagger();
        }
Exemplo n.º 5
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            services.Configure <PlatformOptions>(Configuration.GetSection("VirtoCommerce"));
            services.Configure <HangfireOptions>(Configuration.GetSection("VirtoCommerce:Jobs"));

            PlatformVersion.CurrentVersion = SemanticVersion.Parse(Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.ApplicationVersion);

            services.AddPlatformServices(Configuration);
            services.AddSecurityServices();

            var mvcBuilder = services.AddMvc().AddJsonOptions(options =>
            {
                //Next line needs to represent custom derived types in the resulting swagger doc definitions. Because default SwaggerProvider used global JSON serialization settings
                //we should register this converter globally.
                options.SerializerSettings.ContractResolver = new PolymorphJsonContractResolver();
                //Next line allow to use polymorph types as parameters in API controller methods
                options.SerializerSettings.Converters.Add(new PolymorphJsonConverter());
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateTimeZoneHandling  = DateTimeZoneHandling.Utc;
                options.SerializerSettings.NullValueHandling     = NullValueHandling.Ignore;
                options.SerializerSettings.Converters.Add(new StringEnumConverter());
                options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
                options.SerializerSettings.Formatting = Formatting.None;

                options.SerializerSettings.Error += (sender, args) =>
                {
                    // Expose any JSON serialization exception as HTTP error
                    throw new JsonException(args.ErrorContext.Error.Message);
                };
                options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            }
                                                              )
                             .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            var modulesDiscoveryPath = Path.GetFullPath("Modules");

            services.AddModules(mvcBuilder, options =>
            {
                options.DiscoveryPath = modulesDiscoveryPath;
                options.ProbingPath   = "App_Data/Modules";
            });

            services.Configure <ExternalModuleCatalogOptions>(Configuration.GetSection("ExternalModules"));
            services.AddExternalModules();

            services.AddDbContext <SecurityDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("VirtoCommerce"));
                // Register the entity sets needed by OpenIddict.
                // Note: use the generic overload if you need
                // to replace the default OpenIddict entities.
                options.UseOpenIddict();
            });

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

            services.AddSecurityServices(options =>
            {
                options.NonEditableUsers = new[] { "admin" };
            });

            services.AddIdentity <ApplicationUser, Role>()
            .AddEntityFrameworkStores <SecurityDbContext>()
            .AddDefaultTokenProviders();

            // Configure Identity to use the same JWT claims as OpenIddict instead
            // of the legacy WS-Federation claims it uses by default (ClaimTypes),
            // which saves you from doing the mapping in your authorization controller.
            services.Configure <IdentityOptions>(options =>
            {
                options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
                options.ClaimsIdentity.UserIdClaimType   = OpenIdConnectConstants.Claims.Subject;
                options.ClaimsIdentity.RoleClaimType     = OpenIdConnectConstants.Claims.Role;
            });


            // Register the OAuth2 validation handler.
            services.AddAuthentication().AddOAuthValidation();

            // Register the OpenIddict services.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            services.AddOpenIddict(options =>
            {
                // Register the Entity Framework stores.
                options.AddEntityFrameworkCoreStores <SecurityDbContext>();


                // Register the ASP.NET Core MVC binder used by OpenIddict.
                // Note: if you don't call this method, you won't be able to
                // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
                options.AddMvcBinders();

                // Enable the authorization, logout, token and userinfo endpoints.
                options.EnableTokenEndpoint("/connect/token")
                .EnableUserinfoEndpoint("/api/security/userinfo");

                // Note: the Mvc.Client sample only uses the code flow and the password flow, but you
                // can enable the other flows if you need to support implicit or client credentials.
                options.AllowPasswordFlow()
                .AllowRefreshTokenFlow()
                .AllowClientCredentialsFlow();

                // Make the "client_id" parameter mandatory when sending a token request.
                //options.RequireClientIdentification();

                // When request caching is enabled, authorization and logout requests
                // are stored in the distributed cache by OpenIddict and the user agent
                // is redirected to the same page with a single parameter (request_id).
                // This allows flowing large OpenID Connect requests even when using
                // an external authentication provider like Google, Facebook or Twitter.
                options.EnableRequestCaching();

                // During development, you can disable the HTTPS requirement.
                options.DisableHttpsRequirement();

                // Note: to use JWT access tokens instead of the default
                // encrypted format, the following lines are required:
                //
                options.UseJsonWebTokens();
                //TODO: Replace to X.509 certificate
                options.AddEphemeralSigningKey();
            });

            services.Configure <IdentityOptions>(Configuration.GetSection("IdentityOptions"));

            //always  return 401 instead of 302 for unauthorized  requests
            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = 401;
                    return(Task.CompletedTask);
                };
            });


            services.AddAuthorization();
            // register the AuthorizationPolicyProvider which dynamically registers authorization policies for each permission defined in module manifest
            services.AddSingleton <IAuthorizationPolicyProvider, PermissionAuthorizationPolicyProvider>();
            //Platform authorization handler for policies based on permissions
            services.AddSingleton <IAuthorizationHandler, PermissionAuthorizationHandler>();

            // Add memory cache services
            services.AddMemoryCache();
            //Add Smidge runtime bundling library configuration
            services.AddSmidge(Configuration.GetSection("smidge"), new PhysicalFileProvider(modulesDiscoveryPath));
            services.AddSmidgeNuglify();

            // Register the Swagger generator
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Title       = "VirtoCommerce Solution REST API documentation",
                    Version     = "v1",
                    Description = "For this sample, you can use the"
                    ,
                    Contact = new Contact
                    {
                        Email = "*****@*****.**",
                        Name  = "Virto Commerce",
                        Url   = "http://virtocommerce.com"
                    }
                });
                c.TagActionsBy(api => api.GroupByModuleName(services));
                c.DocInclusionPredicate((docName, api) => true);
                c.DescribeAllEnumsAsStrings();
                c.IgnoreObsoleteProperties();
                c.IgnoreObsoleteActions();
                c.OperationFilter <FileResponseTypeFilter>();
                c.OperationFilter <OptionalParametersFilter>();
                c.OperationFilter <TagsFilter>();
                c.DocumentFilter <TagsFilter>();
                c.MapType <object>(() => new Schema {
                    Type = "object"
                });
                c.AddModulesXmlComments(services);
            });

            //Add SignalR for push notifications
            services.AddSignalR();


            var assetsProvider = Configuration.GetSection("Assets:Provider").Value;

            if (assetsProvider.EqualsInvariant("AzureBlobStorage"))
            {
                var azureBlobOptions = new AzureBlobContentOptions();
                Configuration.GetSection("Assets:AzureBlobStorage").Bind(azureBlobOptions);

                services.AddAzureBlobProvider(options =>
                {
                    options.ConnectionString = azureBlobOptions.ConnectionString;
                    options.CdnUrl           = azureBlobOptions.CdnUrl;
                });
            }
            else
            {
                var fileSystemBlobOptions = new FileSystemBlobContentOptions();
                Configuration.GetSection("Assets:FileSystem").Bind(fileSystemBlobOptions);

                services.AddFileSystemBlobProvider(options =>
                {
                    options.RootPath  = HostingEnvironment.MapPath(fileSystemBlobOptions.RootPath);
                    options.PublicUrl = fileSystemBlobOptions.PublicUrl;
                });
            }

            var hangfireOptions = new HangfireOptions();

            Configuration.GetSection("VirtoCommerce:Hangfire").Bind(hangfireOptions);
            if (hangfireOptions.JobStorageType == HangfireJobStorageType.SqlServer)
            {
                services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("VirtoCommerce")));
            }
            else
            {
                services.AddHangfire(config => config.UseMemoryStorage());
            }
        }
Exemplo n.º 6
0
        public static void SetupContainer(IAppBuilder app, IUnityContainer container, IPathMapper pathMapper,
                                          string virtualRoot, string routePrefix, string modulesPhysicalPath)
        {
            container.RegisterInstance(app);

            var moduleInitializerOptions = (ModuleInitializerOptions)container.Resolve <IModuleInitializerOptions>();

            moduleInitializerOptions.VirtualRoot = virtualRoot;
            moduleInitializerOptions.RoutePrefix = routePrefix;

            //Initialize Platform dependencies
            var connectionString = ConfigurationHelper.GetConnectionStringValue("VirtoCommerce");

            var hangfireOptions = new HangfireOptions
            {
                StartServer              = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Jobs.Enabled", true),
                JobStorageType           = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Jobs.StorageType", "Memory"),
                DatabaseConnectionString = connectionString,
                WorkerCount              = ConfigurationHelper.GetNullableAppSettingsValue("VirtoCommerce:Jobs.WorkerCount", (int?)null)
            };
            var hangfireLauncher = new HangfireLauncher(hangfireOptions);

            InitializePlatform(app, container, pathMapper, connectionString, hangfireLauncher, modulesPhysicalPath);

            var moduleManager = container.Resolve <IModuleManager>();
            var moduleCatalog = container.Resolve <IModuleCatalog>();

            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.EnsureEndSeparator();

            // Register URL rewriter for platform scripts
            var scriptsPhysicalPath        = pathMapper.MapPath(VirtualRoot + "/Scripts").EnsureEndSeparator();
            var scriptsRelativePath        = MakeRelativePath(applicationBase, scriptsPhysicalPath);
            var platformUrlRewriterOptions = new UrlRewriterOptions();

            platformUrlRewriterOptions.Items.Add(PathString.FromUriComponent("/$(Platform)/Scripts"), "");
            app.Use <UrlRewriterOwinMiddleware>(platformUrlRewriterOptions);
            app.UseStaticFiles(new StaticFileOptions
            {
                FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(scriptsRelativePath)
            });

            // Register URL rewriter before modules initialization
            if (Directory.Exists(modulesPhysicalPath))
            {
                var modulesRelativePath = MakeRelativePath(applicationBase, modulesPhysicalPath);

                var urlRewriterOptions = new UrlRewriterOptions();

                foreach (var module in moduleCatalog.Modules.OfType <ManifestModuleInfo>())
                {
                    var urlRewriteKey   = string.Format(CultureInfo.InvariantCulture, "/Modules/$({0})", module.ModuleName);
                    var urlRewriteValue = MakeRelativePath(modulesPhysicalPath, module.FullPhysicalPath);
                    urlRewriterOptions.Items.Add(PathString.FromUriComponent(urlRewriteKey), "/" + urlRewriteValue);

                    moduleInitializerOptions.ModuleDirectories.Add(module.ModuleName, module.FullPhysicalPath);
                }

                app.Use <UrlRewriterOwinMiddleware>(urlRewriterOptions);
                app.UseStaticFiles(new StaticFileOptions
                {
                    FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(modulesRelativePath)
                });
            }

            container.RegisterInstance(GlobalConfiguration.Configuration);

            // Ensure all modules are loaded
            foreach (var module in moduleCatalog.Modules.OfType <ManifestModuleInfo>().Where(x => x.State == ModuleState.NotStarted))
            {
                moduleManager.LoadModule(module.ModuleName);
            }

            SwaggerConfig.RegisterRoutes(container);

            // Post-initialize

            // Register MVC areas unless running in the Web Platform Installer mode
            if (IsApplication)
            {
                AreaRegistration.RegisterAllAreas();
            }

            // Register other MVC resources
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            if (IsApplication)
            {
                RouteConfig.RegisterRoutes(RouteTable.Routes);
            }

            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Security OWIN configuration
            var authenticationOptions = new Core.Security.AuthenticationOptions
            {
                CookiesEnabled             = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookies.Enabled", true),
                CookiesValidateInterval    = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookies.ValidateInterval", TimeSpan.FromDays(1)),
                BearerTokensEnabled        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.Enabled", true),
                BearerTokensExpireTimeSpan = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.AccessTokenExpireTimeSpan", TimeSpan.FromHours(1)),
                HmacEnabled = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Hmac.Enabled", true),
                HmacSignatureValidityPeriod = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Hmac.SignatureValidityPeriod", TimeSpan.FromMinutes(20)),
                ApiKeysEnabled                  = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.Enabled", true),
                ApiKeysHttpHeaderName           = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.HttpHeaderName", "api_key"),
                ApiKeysQueryStringParameterName = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.QueryStringParameterName", "api_key"),
            };

            OwinConfig.Configure(app, container, authenticationOptions);

            hangfireLauncher.ConfigureOwin(app, container);

            RecurringJob.AddOrUpdate <SendNotificationsJobs>("SendNotificationsJob", x => x.Process(), "*/1 * * * *");

            var notificationManager = container.Resolve <INotificationManager>();

            notificationManager.RegisterNotificationType(() => new RegistrationEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Registration notification",
                Description          = "This notification is sent by email to a client when he finishes registration",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.RegistrationNotificationSubject,
                    Body     = PlatformNotificationResource.RegistrationNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Reset password notification",
                Description          = "This notification is sent by email to a client upon reset password request",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.ResetPasswordNotificationSubject,
                    Body     = PlatformNotificationResource.ResetPasswordNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new TwoFactorEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Two factor authentication",
                Description          = "This notification contains a security token for two factor authentication",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.TwoFactorNotificationSubject,
                    Body     = PlatformNotificationResource.TwoFactorNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new TwoFactorSmsNotification(container.Resolve <ISmsNotificationSendingGateway>())
            {
                DisplayName          = "Two factor authentication",
                Description          = "This notification contains a security token for two factor authentication",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.TwoFactorNotificationSubject,
                    Body     = PlatformNotificationResource.TwoFactorNotificationBody,
                    Language = "en-US",
                }
            });

            //Get initialized modules list sorted by dependency order
            var postInitializeModules = moduleCatalog.CompleteListWithDependencies(moduleCatalog.Modules.OfType <ManifestModuleInfo>())
                                        .Where(m => m.ModuleInstance != null && m.State == ModuleState.Initialized)
                                        .ToArray();

            foreach (var module in postInitializeModules)
            {
                moduleManager.PostInitializeModule(module);
            }

            var redisConnectionString = ConfigurationManager.ConnectionStrings["RedisConnectionString"];

            // Redis
            if (redisConnectionString != null && !string.IsNullOrEmpty(redisConnectionString.ConnectionString))
            {
                // Cache
                RedisConfigurations.AddConfiguration(new RedisConfiguration("redisConnectionString", redisConnectionString.ConnectionString));

                // SignalR
                // https://stackoverflow.com/questions/29885470/signalr-scaleout-on-azure-rediscache-connection-issues
                GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(redisConnectionString.ConnectionString, "VirtoCommerce.Platform.SignalR"));
            }

            // SignalR
            var tempCounterManager = new TempPerformanceCounterManager();

            GlobalHost.DependencyResolver.Register(typeof(IPerformanceCounterManager), () => tempCounterManager);
            var hubConfiguration = new HubConfiguration {
                EnableJavaScriptProxies = false
            };

            app.MapSignalR("/" + moduleInitializerOptions.RoutePrefix + "signalr", hubConfiguration);

            // Initialize InstrumentationKey from EnvironmentVariable
            var appInsightKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");

            if (!string.IsNullOrEmpty(appInsightKey))
            {
                TelemetryConfiguration.Active.InstrumentationKey = appInsightKey;
            }
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            services.Configure <DemoOptions>(Configuration.GetSection("VirtoCommerce"));
            services.Configure <HangfireOptions>(Configuration.GetSection("VirtoCommerce:Jobs"));

            PlatformVersion.CurrentVersion = SemanticVersion.Parse(Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.ApplicationVersion);

            var mvcBuilder = services.AddMvc();

            services.AddModules(mvcBuilder, options =>
            {
                options.DiscoveryPath = HostingEnvironment.MapPath(@"~/Modules");
                options.ProbingPath   = HostingEnvironment.MapPath("~/App_Data/Modules");
                options.VirtualPath   = "~/Modules";
            });
            services.AddExternalModules(options =>
            {
                options.ModulesManifestUrl = new Uri(@"https://raw.githubusercontent.com/VirtoCommerce/vc-modules/master/modules.json");
            });

            services.AddDbContext <SecurityDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("VirtoCommerce"));
                // Register the entity sets needed by OpenIddict.
                // Note: use the generic overload if you need
                // to replace the default OpenIddict entities.
                options.UseOpenIddict();
            });

            services.AddIdentity <ApplicationUser, Role>()
            .AddEntityFrameworkStores <SecurityDbContext>()
            .AddDefaultTokenProviders();

            // Configure Identity to use the same JWT claims as OpenIddict instead
            // of the legacy WS-Federation claims it uses by default (ClaimTypes),
            // which saves you from doing the mapping in your authorization controller.
            services.Configure <IdentityOptions>(options =>
            {
                options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
                options.ClaimsIdentity.UserIdClaimType   = OpenIdConnectConstants.Claims.Subject;
                options.ClaimsIdentity.RoleClaimType     = OpenIdConnectConstants.Claims.Role;
            });


            // Register the OAuth2 validation handler.
            services.AddAuthentication().AddOAuthValidation();

            // Register the OpenIddict services.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            services.AddOpenIddict(options =>
            {
                // Register the Entity Framework stores.
                options.AddEntityFrameworkCoreStores <SecurityDbContext>();


                // Register the ASP.NET Core MVC binder used by OpenIddict.
                // Note: if you don't call this method, you won't be able to
                // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
                options.AddMvcBinders();

                // Enable the authorization, logout, token and userinfo endpoints.
                options.EnableTokenEndpoint("/connect/token")
                .EnableUserinfoEndpoint("/api/security/userinfo");

                // Note: the Mvc.Client sample only uses the code flow and the password flow, but you
                // can enable the other flows if you need to support implicit or client credentials.
                options.AllowPasswordFlow()
                .AllowRefreshTokenFlow()
                .AllowClientCredentialsFlow();

                // Make the "client_id" parameter mandatory when sending a token request.
                options.RequireClientIdentification();

                // When request caching is enabled, authorization and logout requests
                // are stored in the distributed cache by OpenIddict and the user agent
                // is redirected to the same page with a single parameter (request_id).
                // This allows flowing large OpenID Connect requests even when using
                // an external authentication provider like Google, Facebook or Twitter.
                options.EnableRequestCaching();

                // During development, you can disable the HTTPS requirement.
                options.DisableHttpsRequirement();

                // Note: to use JWT access tokens instead of the default
                // encrypted format, the following lines are required:
                //
                options.UseJsonWebTokens();
                //TODO: Replace to X.509 certificate
                options.AddEphemeralSigningKey();
            });

            services.Configure <IdentityOptions>(options =>
            {
                // Password settings
                options.Password.RequireDigit           = true;
                options.Password.RequiredLength         = 8;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase       = true;
                options.Password.RequireLowercase       = false;
                options.Password.RequiredUniqueChars    = 6;

                // Lockout settings
                options.Lockout.DefaultLockoutTimeSpan  = TimeSpan.FromMinutes(30);
                options.Lockout.MaxFailedAccessAttempts = 10;
                options.Lockout.AllowedForNewUsers      = true;

                // User settings
                options.User.RequireUniqueEmail = true;
            });

            //always  return 401 instead of 302 for unauthorized  requests
            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = 401;
                    return(Task.CompletedTask);
                };
            });


            services.AddAuthorization();
            // register the AuthorizationPolicyProvider which dynamically registers authorization policies for each permission defined in module manifest
            services.AddSingleton <IAuthorizationPolicyProvider, PermissionAuthorizationPolicyProvider>();
            //Platform authorization handler for policies based on permissions
            services.AddTransient <IAuthorizationHandler, PermissionAuthorizationHandler>();

            // Add memory cache services
            services.AddMemoryCache();
            //Add Smidge runtime bundling library configuration
            services.AddSmidge(Configuration.GetSection("smidge"));
            // Register the Swagger generator
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info {
                    Title = "VirtoCommerce Solution REST API documentation", Version = "v1"
                });
                c.TagActionsBy(api => api.GroupByModuleName(services));
                c.DocInclusionPredicate((docName, api) => true);
                c.DescribeAllEnumsAsStrings();
                c.IgnoreObsoleteProperties();
                c.IgnoreObsoleteActions();
                c.OperationFilter <FileResponseTypeFilter>();
                c.OperationFilter <OptionalParametersFilter>();
                c.OperationFilter <TagsFilter>();
                c.DocumentFilter <TagsFilter>();
                c.MapType <object>(() => new Schema {
                    Type = "object"
                });
                c.AddModulesXmlComments(services);
            });

            //Add SignalR for push notifications
            services.AddSignalR();

            services.AddPlatformServices(Configuration);
            services.AddSecurityServices();

            var hangfireOptions = new HangfireOptions();

            Configuration.GetSection("VirtoCommerce:Hangfire").Bind(hangfireOptions);
            if (hangfireOptions.JobStorageType == HangfireJobStorageType.SqlServer)
            {
                services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("VirtoCommerce")));
            }
            else
            {
                services.AddHangfire(config => config.UseMemoryStorage());
            }
        }
Exemplo n.º 8
0
        public static void SetupContainer(IAppBuilder app, IUnityContainer container, IPathMapper pathMapper,
                                          string virtualRoot, string routePrefix, string modulesPhysicalPath)
        {
            container.RegisterInstance(app);

            var moduleInitializerOptions = (ModuleInitializerOptions)container.Resolve <IModuleInitializerOptions>();

            moduleInitializerOptions.VirtualRoot = virtualRoot;
            moduleInitializerOptions.RoutePrefix = routePrefix;

            //Initialize Platform dependencies
            var connectionString = ConfigurationHelper.GetConnectionStringValue("VirtoCommerce");

            var hangfireOptions = new HangfireOptions
            {
                StartServer              = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Jobs.Enabled", true),
                JobStorageType           = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Jobs.StorageType", "Memory"),
                DatabaseConnectionString = connectionString,
                WorkerCount              = ConfigurationHelper.GetNullableAppSettingsValue("VirtoCommerce:Jobs.WorkerCount", (int?)null)
            };
            var hangfireLauncher = new HangfireLauncher(hangfireOptions);

            var authenticationOptions = new AuthenticationOptions
            {
                AllowOnlyAlphanumericUserNames = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AllowOnlyAlphanumericUserNames", false),
                RequireUniqueEmail             = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:RequireUniqueEmail", false),

                PasswordRequiredLength          = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Password.RequiredLength", 5),
                PasswordRequireNonLetterOrDigit = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Password.RequireNonLetterOrDigit", false),
                PasswordRequireDigit            = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Password.RequireDigit", false),
                PasswordRequireLowercase        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Password.RequireLowercase", false),
                PasswordRequireUppercase        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Password.RequireUppercase", false),

                UserLockoutEnabledByDefault          = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:UserLockoutEnabledByDefault", true),
                DefaultAccountLockoutTimeSpan        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:DefaultAccountLockoutTimeSpan", TimeSpan.FromMinutes(5)),
                MaxFailedAccessAttemptsBeforeLockout = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:MaxFailedAccessAttemptsBeforeLockout", 5),

                DefaultTokenLifespan = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:DefaultTokenLifespan", TimeSpan.FromDays(1)),

                CookiesEnabled          = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookies.Enabled", true),
                CookiesValidateInterval = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookies.ValidateInterval", TimeSpan.FromDays(1)),

                BearerTokensEnabled        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.Enabled", true),
                AccessTokenExpireTimeSpan  = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.AccessTokenExpireTimeSpan", TimeSpan.FromMinutes(30)),
                RefreshTokenExpireTimeSpan = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.RefreshTokenExpireTimeSpan", TimeSpan.FromDays(30)),
                BearerAuthorizationLimitedCookiePermissions = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:BearerTokens.LimitedCookiePermissions", string.Empty),

                HmacEnabled = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Hmac.Enabled", true),
                HmacSignatureValidityPeriod = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Hmac.SignatureValidityPeriod", TimeSpan.FromMinutes(20)),

                ApiKeysEnabled                  = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.Enabled", true),
                ApiKeysHttpHeaderName           = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.HttpHeaderName", "api_key"),
                ApiKeysQueryStringParameterName = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:ApiKeys.QueryStringParameterName", "api_key"),

                AuthenticationMode = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:AuthenticationMode", AuthenticationMode.Active),
                AuthenticationType = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:AuthenticationType", DefaultAuthenticationTypes.ApplicationCookie),
                CookieDomain       = ConfigurationHelper.GetAppSettingsValue <string>("VirtoCommerce:Authentication:Cookie:Domain", null),
                CookieHttpOnly     = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:HttpOnly", true),
                CookieName         = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:Name", CookieAuthenticationDefaults.CookiePrefix + DefaultAuthenticationTypes.ApplicationCookie),
                CookiePath         = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:Path", "/"),
                CookieSecure       = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:Secure", CookieSecureOption.SameAsRequest),
                ExpireTimeSpan     = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:ExpireTimeSpan", TimeSpan.FromDays(14)),
                LoginPath          = new PathString(ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:LoginPath", string.Empty)),
                LogoutPath         = new PathString(ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:LogoutPath", string.Empty)),
                ReturnUrlParameter = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:ReturnUrlParameter", CookieAuthenticationDefaults.ReturnUrlParameter),
                SlidingExpiration  = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:Cookie:SlidingExpiration", true),

                AzureAdAuthenticationEnabled = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.Enabled", false),
                AzureAdAuthenticationType    = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.AuthenticationType", OpenIdConnectAuthenticationDefaults.AuthenticationType),
                AzureAdAuthenticationCaption = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.Caption", OpenIdConnectAuthenticationDefaults.Caption),
                AzureAdApplicationId         = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.ApplicationId", string.Empty),
                AzureAdTenantId        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.TenantId", string.Empty),
                AzureAdInstance        = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.Instance", string.Empty),
                AzureAdDefaultUserType = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Authentication:AzureAD.DefaultUserType", "Manager")
            };

            container.RegisterInstance(authenticationOptions);

            InitializePlatform(app, container, pathMapper, connectionString, hangfireLauncher, modulesPhysicalPath, moduleInitializerOptions);

            var moduleManager = container.Resolve <IModuleManager>();
            var moduleCatalog = container.Resolve <IModuleCatalog>();

            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.EnsureEndSeparator();

            // Register URL rewriter for platform scripts
            var scriptsPhysicalPath        = pathMapper.MapPath(VirtualRoot + "/Scripts").EnsureEndSeparator();
            var scriptsRelativePath        = MakeRelativePath(applicationBase, scriptsPhysicalPath);
            var platformUrlRewriterOptions = new UrlRewriterOptions();

            platformUrlRewriterOptions.Items.Add(PathString.FromUriComponent("/$(Platform)/Scripts"), "");
            app.Use <UrlRewriterOwinMiddleware>(platformUrlRewriterOptions);
            app.UseStaticFiles(new StaticFileOptions
            {
                FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(scriptsRelativePath)
            });

            // Register URL rewriter before modules initialization
            if (Directory.Exists(modulesPhysicalPath))
            {
                var modulesRelativePath = MakeRelativePath(applicationBase, modulesPhysicalPath);

                var urlRewriterOptions = new UrlRewriterOptions();

                foreach (var module in moduleCatalog.Modules.OfType <ManifestModuleInfo>())
                {
                    var urlRewriteKey   = string.Format(CultureInfo.InvariantCulture, "/Modules/$({0})", module.ModuleName);
                    var urlRewriteValue = MakeRelativePath(modulesPhysicalPath, module.FullPhysicalPath);
                    urlRewriterOptions.Items.Add(PathString.FromUriComponent(urlRewriteKey), "/" + urlRewriteValue);

                    moduleInitializerOptions.ModuleDirectories.Add(module.ModuleName, module.FullPhysicalPath);
                }

                app.Use <UrlRewriterOwinMiddleware>(urlRewriterOptions);
                app.UseStaticFiles(new StaticFileOptions
                {
                    FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(modulesRelativePath)
                });
            }

            container.RegisterInstance(GlobalConfiguration.Configuration);

            // Ensure all modules are loaded
            foreach (var module in moduleCatalog.Modules.OfType <ManifestModuleInfo>().Where(x => x.State == ModuleState.NotStarted))
            {
                moduleManager.LoadModule(module.ModuleName);
            }

            SwaggerConfig.RegisterRoutes(container);

            // Post-initialize

            // Register MVC areas unless running in the Web Platform Installer mode
            if (IsApplication)
            {
                AreaRegistration.RegisterAllAreas();
            }

            // Register other MVC resources
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            if (IsApplication)
            {
                RouteConfig.RegisterRoutes(RouteTable.Routes);
            }

            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Security OWIN configuration
            OwinConfig.Configure(app, container);

            hangfireLauncher.ConfigureOwin(app, container);

            RecurringJob.AddOrUpdate <SendNotificationsJobs>("SendNotificationsJob", x => x.Process(), "*/1 * * * *");

            var notificationManager = container.Resolve <INotificationManager>();

            notificationManager.RegisterNotificationType(() => new RegistrationEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Registration notification",
                Description          = "This notification is sent by email to a client when he finishes registration",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.RegistrationNotificationSubject,
                    Body     = PlatformNotificationResource.RegistrationNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Reset password notification",
                Description          = "This notification is sent by email to a client upon reset password request",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.ResetPasswordNotificationSubject,
                    Body     = PlatformNotificationResource.ResetPasswordNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new TwoFactorEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Two factor authentication",
                Description          = "This notification contains a security token for two factor authentication",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.TwoFactorNotificationSubject,
                    Body     = PlatformNotificationResource.TwoFactorNotificationBody,
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new TwoFactorSmsNotification(container.Resolve <ISmsNotificationSendingGateway>())
            {
                DisplayName          = "Two factor authentication",
                Description          = "This notification contains a security token for two factor authentication",
                NotificationTemplate = new NotificationTemplate
                {
                    Subject  = PlatformNotificationResource.TwoFactorNotificationSubject,
                    Body     = PlatformNotificationResource.TwoFactorNotificationBody,
                    Language = "en-US",
                }
            });

            //Get initialized modules list sorted by dependency order
            var postInitializeModules = moduleCatalog.CompleteListWithDependencies(moduleCatalog.Modules.OfType <ManifestModuleInfo>())
                                        .Where(m => m.ModuleInstance != null && m.State == ModuleState.Initialized)
                                        .ToArray();

            foreach (var module in postInitializeModules)
            {
                moduleManager.PostInitializeModule(module);
            }

            // Initialize InstrumentationKey from EnvironmentVariable
            var applicationInsightsInstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");

            if (!string.IsNullOrEmpty(applicationInsightsInstrumentationKey))
            {
                TelemetryConfiguration.Active.InstrumentationKey = applicationInsightsInstrumentationKey;
            }

            // https://docs.microsoft.com/en-us/azure/application-insights/app-insights-live-stream#secure-the-control-channel
            // https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/733#issuecomment-349752497
            // https://github.com/Azure/azure-webjobs-sdk/issues/1349
            var applicationInsightsAuthApiKey = Environment.GetEnvironmentVariable("APPINSIGHTS_QUICKPULSEAUTHAPIKEY");

            if (!string.IsNullOrEmpty(applicationInsightsAuthApiKey))
            {
                var module = TelemetryModules.Instance.Modules.OfType <QuickPulseTelemetryModule>().Single();
                if (module != null)
                {
                    module.AuthenticationApiKey = applicationInsightsAuthApiKey;
                }
            }
        }
Exemplo n.º 9
0
        public void Configuration(IAppBuilder app, string virtualRoot, string routPrefix)
        {
            VirtualRoot = virtualRoot;

            _assembliesPath = HostingEnvironment.MapPath(VirtualRoot + "/App_Data/Modules");
            HostingEnvironment.MapPath(VirtualRoot).EnsureEndSeparator();
            var modulesVirtualPath = VirtualRoot + "/Modules";
            var modulesPhysicalPath = HostingEnvironment.MapPath(modulesVirtualPath).EnsureEndSeparator();

            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;

            //Modules initialization
            var bootstrapper = new VirtoCommercePlatformWebBootstrapper(modulesVirtualPath, modulesPhysicalPath, _assembliesPath);
            bootstrapper.Run();

            var container = bootstrapper.Container;
            container.RegisterInstance(app);

            var moduleInitializerOptions = (ModuleInitializerOptions)container.Resolve<IModuleInitializerOptions>();
            moduleInitializerOptions.VirtualRoot = virtualRoot;
            moduleInitializerOptions.RoutePrefix = routPrefix;

            //Initialize Platform dependencies
            const string connectionStringName = "VirtoCommerce";

            var hangfireOptions = new HangfireOptions
            {
                StartServer = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Jobs.Enabled", true),
                JobStorageType = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Jobs.StorageType", "Memory"),
                DatabaseConnectionStringName = connectionStringName,
            };
            var hangfireLauncher = new HangfireLauncher(hangfireOptions);

            InitializePlatform(app, container, connectionStringName, hangfireLauncher, modulesPhysicalPath);

            var moduleManager = container.Resolve<IModuleManager>();
            var moduleCatalog = container.Resolve<IModuleCatalog>();

            var applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.EnsureEndSeparator();

            // Register URL rewriter for platform scripts
            var scriptsPhysicalPath = HostingEnvironment.MapPath(VirtualRoot + "/Scripts").EnsureEndSeparator();
            var scriptsRelativePath = MakeRelativePath(applicationBase, scriptsPhysicalPath);
            var platformUrlRewriterOptions = new UrlRewriterOptions();
            platformUrlRewriterOptions.Items.Add(PathString.FromUriComponent("/$(Platform)/Scripts"), "");
            app.Use<UrlRewriterOwinMiddleware>(platformUrlRewriterOptions);
            app.UseStaticFiles(new StaticFileOptions
            {
                FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(scriptsRelativePath)
            });

            // Register URL rewriter before modules initialization
            if (Directory.Exists(modulesPhysicalPath))
            {
                var modulesRelativePath = MakeRelativePath(applicationBase, modulesPhysicalPath);

                var urlRewriterOptions = new UrlRewriterOptions();

                foreach (var module in moduleCatalog.Modules.OfType<ManifestModuleInfo>())
                {
                    var urlRewriteKey = string.Format(CultureInfo.InvariantCulture, "/Modules/$({0})", module.ModuleName);
                    var urlRewriteValue = MakeRelativePath(modulesPhysicalPath, module.FullPhysicalPath);
                    urlRewriterOptions.Items.Add(PathString.FromUriComponent(urlRewriteKey), "/" + urlRewriteValue);

                    moduleInitializerOptions.ModuleDirectories.Add(module.ModuleName, module.FullPhysicalPath);
                }

                app.Use<UrlRewriterOwinMiddleware>(urlRewriterOptions);
                app.UseStaticFiles(new StaticFileOptions
                {
                    FileSystem = new Microsoft.Owin.FileSystems.PhysicalFileSystem(modulesRelativePath)
                });
            }

            container.RegisterInstance(GlobalConfiguration.Configuration);

            // Ensure all modules are loaded
            foreach (var module in moduleCatalog.Modules.OfType<ManifestModuleInfo>().Where(x => x.State == ModuleState.NotStarted))
            {
                moduleManager.LoadModule(module.ModuleName);
            }

            SwaggerConfig.RegisterRoutes(container);

            // Post-initialize

            // Platform MVC configuration
            if (IsApplication)
            {
                AreaRegistration.RegisterAllAreas();
            }

            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Security OWIN configuration
            var authenticationOptions = new Core.Security.AuthenticationOptions
            {
                CookiesEnabled = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Cookies.Enabled", true),
                CookiesValidateInterval = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Cookies.ValidateInterval", TimeSpan.FromDays(1)),
                BearerTokensEnabled = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:BearerTokens.Enabled", true),
                BearerTokensExpireTimeSpan = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:BearerTokens.AccessTokenExpireTimeSpan", TimeSpan.FromHours(1)),
                HmacEnabled = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Hmac.Enabled", true),
                HmacSignatureValidityPeriod = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:Hmac.SignatureValidityPeriod", TimeSpan.FromMinutes(20)),
                ApiKeysEnabled = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.Enabled", true),
                ApiKeysHttpHeaderName = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.HttpHeaderName", "api_key"),
                ApiKeysQueryStringParameterName = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Authentication:ApiKeys.QueryStringParameterName", "api_key"),
            };
            OwinConfig.Configure(app, container, authenticationOptions);

            hangfireLauncher.ConfigureOwin(app, container);

            RecurringJob.AddOrUpdate<SendNotificationsJobs>("SendNotificationsJob", x => x.Process(), "*/1 * * * *");

            var notificationManager = container.Resolve<INotificationManager>();
            notificationManager.RegisterNotificationType(() => new RegistrationEmailNotification(container.Resolve<IEmailNotificationSendingGateway>())
            {
                DisplayName = "Registration notification",
                Description = "This notification sends by email to client when he finish registration",
                NotificationTemplate = new NotificationTemplate
                {
                    Body = PlatformNotificationResource.RegistrationNotificationBody,
                    Subject = PlatformNotificationResource.RegistrationNotificationSubject
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordEmailNotification(container.Resolve<IEmailNotificationSendingGateway>())
            {
                DisplayName = "Reset password notification",
                Description = "This notification sends by email to client when he want to reset his password",
                NotificationTemplate = new NotificationTemplate
                {
                    Body = PlatformNotificationResource.ResetPasswordNotificationBody,
                    Subject = PlatformNotificationResource.ResetPasswordNotificationSubject
                }
            });

            var postInitializeModules = moduleCatalog.CompleteListWithDependencies(moduleCatalog.Modules.OfType<ManifestModuleInfo>())
                .Where(m => m.ModuleInstance != null)
                .ToArray();

            foreach (var module in postInitializeModules)
            {
                moduleManager.PostInitializeModule(module);
            }

            // SignalR
            var tempCounterManager = new TempPerformanceCounterManager();
            GlobalHost.DependencyResolver.Register(typeof(IPerformanceCounterManager), () => tempCounterManager);
            var hubConfiguration = new HubConfiguration { EnableJavaScriptProxies = false };
            app.MapSignalR("/" + moduleInitializerOptions.RoutePrefix + "signalr", hubConfiguration);

            //Start background sample data installation if in config set concrete zip path (need for demo)
            //var settingManager = container.Resolve<ISettingsManager>();
            //var sampleDataState = EnumUtility.SafeParse<VirtoCommerce.Platform.Web.Model.ExportImport.SampleDataState>(settingManager.GetValue<string>("VirtoCommerce.SampleDataState", VirtoCommerce.Platform.Web.Model.ExportImport.SampleDataState.Undefined.ToString()), VirtoCommerce.Platform.Web.Model.ExportImport.SampleDataState.Undefined);
            //if (sampleDataState == Model.ExportImport.SampleDataState.Undefined)
            //{
            //    var sampleDataUrl = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:SampleDataUrl", string.Empty);
            //    if (!string.IsNullOrEmpty(sampleDataUrl) && sampleDataUrl.EndsWith(".zip"))
            //    {
            //        var exportImportController = container.Resolve<PlatformExportImportController>();
            //        exportImportController.ImportSampleData(sampleDataUrl);
            //    }
            //}
        }
Exemplo n.º 10
0
        public static IGlobalConfiguration UseHangfireDashboardExtention(this IGlobalConfiguration config, HangfireOptions options = null)
        {
            if (options == null)
            {
                options = new HangfireOptions();
            }
            var assembly = typeof(HangfireOptions).GetTypeInfo().Assembly;

            NavigationMenu.Items.Add(page => new MenuItem("Add jobs", page.Url.To("/addjobs"))
            {
                Active = page.RequestPath.StartsWith("/addjobs")
            });

            DashboardRoutes.Routes.Add("/dispatcher", new HttpJobDispatcher());
            DashboardRoutes.Routes.AddRazorPage("/addjobs", x => new AddJobPage());

            var jsPath = DashboardRoutes.Routes.Contains("/js[0-9]+") ? "/js[0-9]+" : "/js[0-9]{3}";

            DashboardRoutes.Routes.Append(jsPath, new EmbeddedResourceDispatcher(assembly, "JobService.Dashboard.Content.addjob.js"));
            DashboardRoutes.Routes.Append(jsPath, new EmbeddedResourceDispatcher(assembly, "JobService.Dashboard.Content.cron.js"));
            DashboardRoutes.Routes.Append(jsPath, new DynamicJsDispatcher(options));

            return(config);
        }