예제 #1
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>();
            var assembly            = typeof(LiquidNotificationTemplateResolver).Assembly;

            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
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.RegistrationNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.RegistrationNotificationTemplateSubject.html").ReadToString(),
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordEmailNotification(container.Resolve <IEmailNotificationSendingGateway>())
            {
                DisplayName          = "Reset password email notification",
                Description          = "This notification is sent by email to a client upon reset password request",
                NotificationTemplate = new NotificationTemplate
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ResetPasswordNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ResetPasswordNotificationTemplateSubject.html").ReadToString(),
                    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
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.TwoFactorNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.TwoFactorNotificationTemplateSubject.html").ReadToString(),
                    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
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.TwoFactorNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.TwoFactorNotificationTemplateSubject.html").ReadToString(),
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new ResetPasswordSmsNotification(container.Resolve <ISmsNotificationSendingGateway>())
            {
                DisplayName          = "Reset password sms notification",
                Description          = "This notification is sent by sms to a client upon reset password request",
                NotificationTemplate = new NotificationTemplate
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ResetPasswordSmsNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ResetPasswordSmsNotificationTemplateSubject.html").ReadToString(),
                    Language = "en-US",
                }
            });

            notificationManager.RegisterNotificationType(() => new ChangePhoneNumberSmsNotification(container.Resolve <ISmsNotificationSendingGateway>())
            {
                DisplayName          = "Change phone number sms notification",
                Description          = "This notification is sent by sms to a client upon change phone number request",
                NotificationTemplate = new NotificationTemplate
                {
                    Body     = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ChangePhoneNumberSmsNotificationTemplateBody.html").ReadToString(),
                    Subject  = assembly.GetManifestResourceStream("VirtoCommerce.Platform.Data.Notifications.Templates.ChangePhoneNumberSmsNotificationTemplateSubject.html").ReadToString(),
                    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;
                }
            }
        }
예제 #2
0
        private static void InitializePlatform(
            IAppBuilder app,
            IUnityContainer container,
            IPathMapper pathMapper,
            string connectionString,
            HangfireLauncher hangfireLauncher,
            string modulesPath,
            ModuleInitializerOptions moduleInitializerOptions)
        {
            container.RegisterType <ICurrentUser, CurrentUser>(new HttpContextLifetimeManager());
            container.RegisterType <IUserNameResolver, UserNameResolver>();

            #region Setup database

            using (var db = new SecurityDbContext(connectionString))
            {
                new IdentityDatabaseInitializer().InitializeDatabase(db);
            }

            using (var context = new PlatformRepository(connectionString, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor()))
            {
                new PlatformDatabaseInitializer().InitializeDatabase(context);
            }

            hangfireLauncher.ConfigureDatabase();

            #endregion

            Func <IPlatformRepository> platformRepositoryFactory = () => new PlatformRepository(connectionString, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor());
            container.RegisterType <IPlatformRepository>(new InjectionFactory(c => platformRepositoryFactory()));
            container.RegisterInstance(platformRepositoryFactory);
            var moduleCatalog = container.Resolve <IModuleCatalog>();

            #region Caching

            //Cure for System.Runtime.Caching.MemoryCache freezing
            //https://www.zpqrtbnk.net/posts/appdomains-threads-cultureinfos-and-paracetamol
            app.SanitizeThreadCulture();
            ICacheManager <object> cacheManager = null;

            var redisConnectionString = ConfigurationHelper.GetConnectionStringValue("RedisConnectionString");

            //Try to load cache configuration from web.config first
            //Should be aware to using Web cache cache handle because it not worked in native threads. (Hangfire jobs)
            if (ConfigurationManager.GetSection(CacheManagerSection.DefaultSectionName) is CacheManagerSection cacheManagerSection)
            {
                CacheManagerConfiguration configuration = null;

                var defaultCacheManager = cacheManagerSection.CacheManagers.FirstOrDefault(p => p.Name.EqualsInvariant("platformCache"));
                if (defaultCacheManager != null)
                {
                    configuration = ConfigurationBuilder.LoadConfiguration(defaultCacheManager.Name);
                }

                var redisCacheManager = cacheManagerSection.CacheManagers.FirstOrDefault(p => p.Name.EqualsInvariant("redisPlatformCache"));
                if (redisConnectionString != null && redisCacheManager != null)
                {
                    configuration = ConfigurationBuilder.LoadConfiguration(redisCacheManager.Name);
                }

                if (configuration != null)
                {
                    configuration.LoggerFactoryType          = typeof(CacheManagerLoggerFactory);
                    configuration.LoggerFactoryTypeArguments = new object[] { container.Resolve <ILog>() };
                    cacheManager = CacheFactory.FromConfiguration <object>(configuration);
                }
            }

            // Create a default cache manager if there is no any others
            if (cacheManager == null)
            {
                cacheManager = CacheFactory.Build("platformCache", settings =>
                {
                    settings.WithUpdateMode(CacheUpdateMode.Up)
                    .WithSystemRuntimeCacheHandle("memCacheHandle")
                    .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromMinutes(5));
                });
            }

            container.RegisterInstance(cacheManager);

            #endregion

            #region Settings

            var platformModuleManifest = new ModuleManifest
            {
                Id              = "VirtoCommerce.Platform",
                Version         = PlatformVersion.CurrentVersion.ToString(),
                PlatformVersion = PlatformVersion.CurrentVersion.ToString(),
                Settings        = new[]
                {
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendGrid",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendGrid.ApiKey",
                                ValueType   = ModuleSetting.TypeSecureString,
                                Title       = "SendGrid API key",
                                Description = "Your SendGrid API key"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendingJob",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendingJob.TakeCount",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Job Take Count",
                                Description = "Take count for sending job"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SmtpClient",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Host",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server host",
                                Description = "Smtp server host"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Port",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Smtp server port",
                                Description = "Smtp server port"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Login",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server login",
                                Description = "Smtp server login"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Password",
                                ValueType   = ModuleSetting.TypeSecureString,
                                Title       = "Smtp server password",
                                Description = "Smtp server password"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.UseSsl",
                                ValueType   = ModuleSetting.TypeBoolean,
                                Title       = "Use SSL",
                                Description = "Use secure connection"
                            },
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Security",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.Security.AccountTypes",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Account types",
                                Description  = "Dictionary for possible account types",
                                IsArray      = true,
                                ArrayValues  = Enum.GetNames(typeof(AccountType)),
                                DefaultValue = AccountType.Manager.ToString()
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Profile",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name      = "VirtoCommerce.Platform.UI.MainMenu.State",
                                ValueType = ModuleSetting.TypeJson,
                                Title     = "Persisted state of main menu"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Language",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Language",
                                Description  = "Default language (two letter code from ISO 639-1, case-insensitive). Example: en, de",
                                DefaultValue = "en"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.RegionalFormat",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Regional format",
                                Description  = "Default regional format (CLDR locale code, with dash or underscore as delemiter, case-insensitive). Example: en, en_US, sr_Cyrl, sr_Cyrl_RS",
                                DefaultValue = "en"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.UI.TimeZone",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Time zone",
                                Description = "Default time zone (IANA time zone name [tz database], exactly as in database, case-sensitive). Examples: America/New_York, Europe/Moscow"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.ShowMeridian",
                                ValueType    = ModuleSetting.TypeBoolean,
                                Title        = "Meridian labels based on user preferences",
                                Description  = "When set to true (by default), system will display time in format like '12 hour format' when possible",
                                DefaultValue = true.ToString()
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.UseTimeAgo",
                                ValueType    = ModuleSetting.TypeBoolean,
                                Title        = "Use time ago format when is possible",
                                Description  = "When set to true (by default), system will display date in format like 'a few seconds ago' when possible",
                                DefaultValue = true.ToString()
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.UI.FullDateThreshold",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Full date threshold",
                                Description = "Number of units after time ago format will be switched to full date format"
                            },
                            new ModuleSetting
                            {
                                Name          = "VirtoCommerce.Platform.UI.FullDateThresholdUnit",
                                ValueType     = ModuleSetting.TypeString,
                                Title         = "Full date threshold unit",
                                Description   = "Unit of full date threshold",
                                DefaultValue  = "Never",
                                AllowedValues = new[]
                                {
                                    "Never",
                                    "Seconds",
                                    "Minutes",
                                    "Hours",
                                    "Days",
                                    "Weeks",
                                    "Months",
                                    "Quarters",
                                    "Years"
                                }
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.FourDecimalsInMoney",
                                ValueType    = ModuleSetting.TypeBoolean,
                                Title        = "Show 4 decimal digits for money",
                                Description  = "Set to true to show 4 decimal digits for money. By default - false, 2 decimal digits are shown.",
                                DefaultValue = "false",
                            },
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Interface",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Customization",
                                ValueType    = ModuleSetting.TypeJson,
                                Title        = "Customization",
                                Description  = "JSON contains personalization settings of manager UI",
                                DefaultValue = "{\n" +
                                               "  \"title\": \"Virto Commerce\",\n" +
                                               "  \"logo\": \"Content/themes/main/images/logo.png\",\n" +
                                               "  \"contrast_logo\": \"Content/themes/main/images/contrast-logo.png\",\n" +
                                               "  \"favicon\": \"favicon.ico\"\n" +
                                               "}"
                            }
                        }
                    }
                }
            };

            var settingsManager = new SettingsManager(moduleCatalog, platformRepositoryFactory, cacheManager, new[] { new ManifestModuleInfo(platformModuleManifest) });
            container.RegisterInstance <ISettingsManager>(settingsManager);

            #endregion

            #region Dynamic Properties

            container.RegisterType <IDynamicPropertyService, DynamicPropertyService>(new ContainerControlledLifetimeManager());

            #endregion

            #region Notifications

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

                // SignalR
                // https://stackoverflow.com/questions/29885470/signalr-scaleout-on-azure-rediscache-connection-issues
                GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(redisConnectionString, "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);

            var hubSignalR = GlobalHost.ConnectionManager.GetHubContext <ClientPushHub>();
            var notifier   = new InMemoryPushNotificationManager(hubSignalR);
            container.RegisterInstance <IPushNotificationManager>(notifier);

            var resolver = new LiquidNotificationTemplateResolver();
            container.RegisterInstance <INotificationTemplateResolver>(resolver);

            var notificationTemplateService = new NotificationTemplateServiceImpl(platformRepositoryFactory);
            container.RegisterInstance <INotificationTemplateService>(notificationTemplateService);

            var notificationManager = new NotificationManager(resolver, platformRepositoryFactory, notificationTemplateService);
            container.RegisterInstance <INotificationManager>(notificationManager);

            IEmailNotificationSendingGateway emailNotificationSendingGateway = null;

            var emailNotificationSendingGatewayName = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:Gateway", "Default");

            if (string.Equals(emailNotificationSendingGatewayName, "Default", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new DefaultSmtpEmailNotificationSendingGateway(settingsManager);
            }
            else if (string.Equals(emailNotificationSendingGatewayName, "SendGrid", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new SendGridEmailNotificationSendingGateway(settingsManager);
            }

            if (emailNotificationSendingGateway != null)
            {
                container.RegisterInstance(emailNotificationSendingGateway);
            }

            ISmsNotificationSendingGateway smsNotificationSendingGateway = null;
            var smsNotificationSendingGatewayName = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway", "Default");

            if (smsNotificationSendingGatewayName.EqualsInvariant("Default"))
            {
                smsNotificationSendingGateway = new DefaultSmsNotificationSendingGateway();
            }
            else if (smsNotificationSendingGatewayName.EqualsInvariant("Twilio"))
            {
                smsNotificationSendingGateway = new TwilioSmsNotificationSendingGateway(new TwilioSmsGatewayOptions
                {
                    AccountId       = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:AccountId"),
                    AccountPassword = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:AccountPassword"),
                    Sender          = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:Sender"),
                });
            }
            else if (smsNotificationSendingGatewayName.EqualsInvariant("ASPSMS"))
            {
                smsNotificationSendingGateway = new AspsmsSmsNotificationSendingGateway(new AspsmsSmsGatewayOptions
                {
                    AccountId       = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:AccountId"),
                    AccountPassword = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:AccountPassword"),
                    Sender          = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:Sender"),
                    JsonApiUri      = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:Notifications:SmsGateway:ASPSMS:JsonApiUri"),
                });
            }

            if (smsNotificationSendingGateway != null)
            {
                container.RegisterInstance(smsNotificationSendingGateway);
            }

            #endregion

            #region Assets

            var blobConnectionString = BlobConnectionString.Parse(ConfigurationHelper.GetConnectionStringValue("AssetsConnectionString"));

            if (string.Equals(blobConnectionString.Provider, FileSystemBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var fileSystemBlobProvider = new FileSystemBlobProvider(NormalizePath(pathMapper, blobConnectionString.RootPath), blobConnectionString.PublicUrl);

                container.RegisterInstance <IBlobStorageProvider>(fileSystemBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(fileSystemBlobProvider);
            }
            else if (string.Equals(blobConnectionString.Provider, AzureBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var azureBlobProvider = new AzureBlobProvider(blobConnectionString.ConnectionString, blobConnectionString.CdnUrl);
                container.RegisterInstance <IBlobStorageProvider>(azureBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(azureBlobProvider);
            }

            container.RegisterType <IAssetEntryService, AssetEntryService>(new ContainerControlledLifetimeManager());
            container.RegisterType <IAssetEntrySearchService, AssetEntryService>(new ContainerControlledLifetimeManager());

            #endregion

            #region Modularity

            var modulesDataSources    = ConfigurationHelper.SplitAppSettingsStringValue("VirtoCommerce:ModulesDataSources");
            var externalModuleCatalog = new ExternalManifestModuleCatalog(moduleCatalog.Modules, modulesDataSources, container.Resolve <ILog>());
            container.RegisterType <ModulesController>(new InjectionConstructor(externalModuleCatalog, new ModuleInstaller(modulesPath, externalModuleCatalog), notifier, container.Resolve <IUserNameResolver>(), settingsManager));

            #endregion

            #region ChangeLogging

            var changeLogService = new ChangeLogService(platformRepositoryFactory);
            container.RegisterInstance <IChangeLogService>(changeLogService);

            #endregion

            #region Security
            container.RegisterInstance <IPermissionScopeService>(new PermissionScopeService());
            container.RegisterType <IRoleManagementService, RoleManagementService>(new ContainerControlledLifetimeManager());

            var apiAccountProvider = new ApiAccountProvider(platformRepositoryFactory, cacheManager);
            container.RegisterInstance <IApiAccountProvider>(apiAccountProvider);

            container.RegisterType <IClaimsIdentityProvider, ApplicationClaimsIdentityProvider>(new ContainerControlledLifetimeManager());

            container.RegisterInstance(app.GetDataProtectionProvider());
            container.RegisterType <SecurityDbContext>(new InjectionConstructor(connectionString));
            container.RegisterType <IUserStore <ApplicationUser>, ApplicationUserStore>();
            container.RegisterType <IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
            container.RegisterType <ApplicationUserManager>();
            container.RegisterType <ApplicationSignInManager>();

            var nonEditableUsers = ConfigurationHelper.GetAppSettingsValue("VirtoCommerce:NonEditableUsers", string.Empty);
            container.RegisterInstance <ISecurityOptions>(new SecurityOptions(nonEditableUsers));

            container.RegisterType <ISecurityService, SecurityService>();

            container.RegisterType <IPasswordCheckService, PasswordCheckService>();

            #endregion

            #region ExportImport
            container.RegisterType <IPlatformExportImportManager, PlatformExportImportManager>();
            #endregion

            #region Serialization

            container.RegisterType <IExpressionSerializer, XmlExpressionSerializer>();

            #endregion

            #region Events
            var inProcessBus = new InProcessBus();
            container.RegisterInstance <IHandlerRegistrar>(inProcessBus);
            container.RegisterInstance <IEventPublisher>(inProcessBus);

            inProcessBus.RegisterHandler <UserChangedEvent>(async(message, token) => await container.Resolve <LogChangesUserChangedEventHandler>().Handle(message));
            inProcessBus.RegisterHandler <UserPasswordChangedEvent>(async(message, token) => await container.Resolve <LogChangesUserChangedEventHandler>().Handle(message));
            inProcessBus.RegisterHandler <UserResetPasswordEvent>(async(message, token) => await container.Resolve <LogChangesUserChangedEventHandler>().Handle(message));
            #endregion
        }
예제 #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 VirtoCommercePlatformWebBootstrapper(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 = "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);

            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)
                });
            }

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

            // 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,
                    Language = "en-US"
                }
            });

            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,
                    Language = "en-US"
                }
            });

            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);

            //Start background sample data installation if in config set concrete zip path (need for demo)
            var settingManager = container.Resolve <ISettingsManager>();

            if (!settingManager.GetValue("VirtoCommerce:SampleDataInstalled", false))
            {
                var sampleDataUrl = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:SampleDataUrl", string.Empty);
                if (!string.IsNullOrEmpty(sampleDataUrl) && sampleDataUrl.EndsWith(".zip"))
                {
                    var exportImportController = container.Resolve <PlatformExportImportController>();
                    exportImportController.TryToImportSampleData(sampleDataUrl);
                }
            }
        }
예제 #4
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;
            }
        }
예제 #5
0
        private static void InitializePlatform(IAppBuilder app, IUnityContainer container, string connectionStringName, HangfireLauncher hangfireLauncher)
        {
            container.RegisterType <ICurrentUser, CurrentUser>(new HttpContextLifetimeManager());
            container.RegisterType <IUserNameResolver, UserNameResolver>();

            #region Setup database

            using (var db = new SecurityDbContext(connectionStringName))
            {
                new IdentityDatabaseInitializer().InitializeDatabase(db);
            }

            using (var context = new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor()))
            {
                new PlatformDatabaseInitializer().InitializeDatabase(context);
            }

            hangfireLauncher.ConfigureDatabase();

            #endregion


            Func <IPlatformRepository> platformRepositoryFactory = () => new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor());
            container.RegisterType <IPlatformRepository>(new InjectionFactory(c => platformRepositoryFactory()));
            container.RegisterInstance(platformRepositoryFactory);
            var moduleCatalog    = container.Resolve <IModuleCatalog>();
            var manifestProvider = container.Resolve <IModuleManifestProvider>();

            #region Caching
            var cacheManager = CacheFactory.Build("platformCache", settings =>
            {
                //Should be aware to using Web cache cache handle because it not worked in native threads. (Hangfire jobs)
                settings
                .WithUpdateMode(CacheUpdateMode.Up)
                .WithSystemRuntimeCacheHandle("memCacheHandle")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromDays(1));
            });
            container.RegisterInstance(cacheManager);
            #endregion

            #region Settings

            var platformSettings = new[]
            {
                new ModuleManifest
                {
                    Settings = new[]
                    {
                        new ModuleSettingsGroup
                        {
                            Name     = "Platform|Notifications|SendGrid",
                            Settings = new []
                            {
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SendGrid.UserName",
                                    ValueType   = ModuleSetting.TypeString,
                                    Title       = "SendGrid UserName",
                                    Description = "Your SendGrid account username"
                                },
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SendGrid.Secret",
                                    ValueType   = ModuleSetting.TypeString,
                                    Title       = "SendGrid Password",
                                    Description = "Your SendGrid account password"
                                }
                            }
                        },

                        new ModuleSettingsGroup
                        {
                            Name     = "Platform|Notifications|SendingJob",
                            Settings = new []
                            {
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SendingJob.TakeCount",
                                    ValueType   = ModuleSetting.TypeInteger,
                                    Title       = "Job Take Count",
                                    Description = "Take count for sending job"
                                }
                            }
                        },

                        new ModuleSettingsGroup
                        {
                            Name     = "Platform|Notifications|SmtpClient",
                            Settings = new []
                            {
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Host",
                                    ValueType   = ModuleSetting.TypeString,
                                    Title       = "Smtp server host",
                                    Description = "Smtp server host"
                                },
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Port",
                                    ValueType   = ModuleSetting.TypeInteger,
                                    Title       = "Smtp server port",
                                    Description = "Smtp server port"
                                },
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Login",
                                    ValueType   = ModuleSetting.TypeString,
                                    Title       = "Smtp server login",
                                    Description = "Smtp server login"
                                },
                                new ModuleSetting
                                {
                                    Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Password",
                                    ValueType   = ModuleSetting.TypeString,
                                    Title       = "Smtp server password",
                                    Description = "Smtp server password"
                                }
                            }
                        },

                        new ModuleSettingsGroup
                        {
                            Name     = "Platform|Security",
                            Settings = new []
                            {
                                new ModuleSetting
                                {
                                    Name         = "VirtoCommerce.Platform.Security.AccountTypes",
                                    ValueType    = ModuleSetting.TypeString,
                                    Title        = "Account types",
                                    Description  = "Dictionary for possible account types",
                                    IsArray      = true,
                                    ArrayValues  = Enum.GetNames(typeof(AccountType)),
                                    DefaultValue = AccountType.Manager.ToString()
                                }
                            }
                        }
                    }
                }
            };

            var settingsManager = new SettingsManager(manifestProvider, platformRepositoryFactory, cacheManager, platformSettings);
            container.RegisterInstance <ISettingsManager>(settingsManager);

            #endregion

            #region Dynamic Properties

            container.RegisterType <IDynamicPropertyService, DynamicPropertyService>(new ContainerControlledLifetimeManager());

            #endregion

            #region Notifications

            var hubSignalR = GlobalHost.ConnectionManager.GetHubContext <ClientPushHub>();
            var notifier   = new InMemoryPushNotificationManager(hubSignalR);
            container.RegisterInstance <IPushNotificationManager>(notifier);

            var resolver = new LiquidNotificationTemplateResolver();
            var notificationTemplateService = new NotificationTemplateServiceImpl(platformRepositoryFactory);
            var notificationManager         = new NotificationManager(resolver, platformRepositoryFactory, notificationTemplateService);

            //var emailNotificationSendingGateway = new DefaultEmailNotificationSendingGateway(settingsManager);
            var emailNotificationSendingGateway = new DefaultSmtpEmailNotificationSendingGateway(settingsManager);

            var defaultSmsNotificationSendingGateway = new DefaultSmsNotificationSendingGateway();

            container.RegisterInstance <INotificationTemplateService>(notificationTemplateService);
            container.RegisterInstance <INotificationManager>(notificationManager);
            container.RegisterInstance <INotificationTemplateResolver>(resolver);
            container.RegisterInstance <IEmailNotificationSendingGateway>(emailNotificationSendingGateway);
            container.RegisterInstance <ISmsNotificationSendingGateway>(defaultSmsNotificationSendingGateway);


            #endregion

            #region Assets

            var blobConnectionString = BlobConnectionString.Parse(ConfigurationManager.ConnectionStrings["AssetsConnectionString"].ConnectionString);

            if (string.Equals(blobConnectionString.Provider, FileSystemBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var fileSystemBlobProvider = new FileSystemBlobProvider(NormalizePath(blobConnectionString.RootPath), blobConnectionString.PublicUrl);

                container.RegisterInstance <IBlobStorageProvider>(fileSystemBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(fileSystemBlobProvider);
            }
            else if (string.Equals(blobConnectionString.Provider, AzureBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var azureBlobProvider = new AzureBlobProvider(blobConnectionString.ConnectionString);
                container.RegisterInstance <IBlobStorageProvider>(azureBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(azureBlobProvider);
            }


            #endregion

            #region Packaging

            var packagesPath   = HostingEnvironment.MapPath(VirtualRoot + "/App_Data/InstalledPackages");
            var packageService = new ZipPackageService(moduleCatalog, manifestProvider, packagesPath);
            container.RegisterInstance <IPackageService>(packageService);

            var uploadsPath = HostingEnvironment.MapPath(VirtualRoot + "/App_Data/Uploads");
            container.RegisterType <ModulesController>(new InjectionConstructor(packageService, uploadsPath, notifier, container.Resolve <IUserNameResolver>()));

            #endregion

            #region ChangeLogging

            var changeLogService = new ChangeLogService(platformRepositoryFactory);
            container.RegisterInstance <IChangeLogService>(changeLogService);

            #endregion

            #region Security
            container.RegisterInstance <IPermissionScopeService>(new PermissionScopeService());
            container.RegisterType <IRoleManagementService, RoleManagementService>(new ContainerControlledLifetimeManager());

            var apiAccountProvider = new ApiAccountProvider(platformRepositoryFactory, cacheManager);
            container.RegisterInstance <IApiAccountProvider>(apiAccountProvider);

            container.RegisterType <IClaimsIdentityProvider, ApplicationClaimsIdentityProvider>(new ContainerControlledLifetimeManager());

            container.RegisterInstance(app.GetDataProtectionProvider());
            container.RegisterType <SecurityDbContext>(new InjectionConstructor(connectionStringName));
            container.RegisterType <IUserStore <ApplicationUser>, ApplicationUserStore>();
            container.RegisterType <IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
            container.RegisterType <ApplicationUserManager>();
            container.RegisterType <ApplicationSignInManager>();

            var nonEditableUsers = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:NonEditableUsers", string.Empty);
            container.RegisterInstance <ISecurityOptions>(new SecurityOptions(nonEditableUsers));

            container.RegisterType <ISecurityService, SecurityService>();

            #endregion

            #region ExportImport
            container.RegisterType <IPlatformExportImportManager, PlatformExportImportManager>();
            #endregion
        }
예제 #6
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();

            // Try to include modules directory to shadow copy directories
            // Ignore any errors, because method AppDomain.CurrentDomain.SetShadowCopyPath is obsolete
            try
            {
#pragma warning disable 618
                AppDomain.CurrentDomain.SetShadowCopyPath(AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories + ";" + _assembliesPath);
#pragma warning restore 618
            }
            catch (Exception)
            {
            }

            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 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 when he want to reset his password",
                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);
            }

            // 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;
            }
        }
예제 #7
0
        private static void InitializePlatform(IAppBuilder app, IUnityContainer container, string connectionStringName, HangfireLauncher hangfireLauncher, string modulesPath)
        {
            container.RegisterType <ICurrentUser, CurrentUser>(new HttpContextLifetimeManager());
            container.RegisterType <IUserNameResolver, UserNameResolver>();

            #region Setup database

            using (var db = new SecurityDbContext(connectionStringName))
            {
                new IdentityDatabaseInitializer().InitializeDatabase(db);
            }

            using (var context = new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor()))
            {
                new PlatformDatabaseInitializer().InitializeDatabase(context);
            }

            hangfireLauncher.ConfigureDatabase();

            #endregion


            Func <IPlatformRepository> platformRepositoryFactory = () => new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor());
            container.RegisterType <IPlatformRepository>(new InjectionFactory(c => platformRepositoryFactory()));
            container.RegisterInstance(platformRepositoryFactory);
            var moduleCatalog = container.Resolve <IModuleCatalog>();

            #region Caching
            ICacheManager <object> cacheManager = null;
            //Try to load cache configuration from web.config first
            if (ConfigurationManager.GetSection(CacheManagerSection.DefaultSectionName) != null)
            {
                cacheManager = CacheFactory.FromConfiguration <object>("platformCache");
            }
            else
            {
                cacheManager = CacheFactory.Build("platformCache", settings =>
                {
                    //Should be aware to using Web cache cache handle because it not worked in native threads. (Hangfire jobs)
                    settings.WithUpdateMode(CacheUpdateMode.Up)
                    .WithSystemRuntimeCacheHandle("memCacheHandle")
                    .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromDays(1));
                });
            }
            container.RegisterInstance(cacheManager);
            #endregion

            #region Settings

            var platformModuleManifest = new ModuleManifest
            {
                Id              = "VirtoCommerce.Platform",
                Version         = PlatformVersion.CurrentVersion.ToString(),
                PlatformVersion = PlatformVersion.CurrentVersion.ToString(),
                Settings        = new[]
                {
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendGrid",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendGrid.ApiKey",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "SendGrid API key",
                                Description = "Your SendGrid API key"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendingJob",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendingJob.TakeCount",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Job Take Count",
                                Description = "Take count for sending job"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SmtpClient",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Host",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server host",
                                Description = "Smtp server host"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Port",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Smtp server port",
                                Description = "Smtp server port"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Login",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server login",
                                Description = "Smtp server login"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Password",
                                ValueType   = ModuleSetting.TypeSecureString,
                                Title       = "Smtp server password",
                                Description = "Smtp server password"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.UseSsl",
                                ValueType   = ModuleSetting.TypeBoolean,
                                Title       = "Use SSL",
                                Description = "Use secure connection"
                            },
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Security",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.Security.AccountTypes",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Account types",
                                Description  = "Dictionary for possible account types",
                                IsArray      = true,
                                ArrayValues  = Enum.GetNames(typeof(AccountType)),
                                DefaultValue = AccountType.Manager.ToString()
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Profile",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name      = "VirtoCommerce.Platform.UI.MainMenu.State",
                                ValueType = ModuleSetting.TypeJson,
                                Title     = "Persisted state of main menu"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Language",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Language",
                                Description  = "Default language (two letter code from ISO 639-1)",
                                DefaultValue = "en"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Interface",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Customization",
                                ValueType    = ModuleSetting.TypeJson,
                                Title        = "Customization",
                                Description  = "JSON contains personalization settings of manager UI",
                                DefaultValue = "{\n" +
                                               "  \"title\": \"Virto Commerce\",\n" +
                                               "  \"logo\": \"Content/themes/main/images/logo.png\",\n" +
                                               "  \"contrast_logo\": \"Content/themes/main/images/contrast-logo.png\"\n" +
                                               "}"
                            }
                        }
                    }
                }
            };

            var settingsManager = new SettingsManager(moduleCatalog, platformRepositoryFactory, cacheManager, new[] { new ManifestModuleInfo(platformModuleManifest) });
            container.RegisterInstance <ISettingsManager>(settingsManager);

            #endregion

            #region Dynamic Properties

            container.RegisterType <IDynamicPropertyService, DynamicPropertyService>(new ContainerControlledLifetimeManager());

            #endregion

            #region Notifications

            var hubSignalR = GlobalHost.ConnectionManager.GetHubContext <ClientPushHub>();
            var notifier   = new InMemoryPushNotificationManager(hubSignalR);
            container.RegisterInstance <IPushNotificationManager>(notifier);

            var resolver = new LiquidNotificationTemplateResolver();
            container.RegisterInstance <INotificationTemplateResolver>(resolver);

            var notificationTemplateService = new NotificationTemplateServiceImpl(platformRepositoryFactory);
            container.RegisterInstance <INotificationTemplateService>(notificationTemplateService);

            var notificationManager = new NotificationManager(resolver, platformRepositoryFactory, notificationTemplateService);
            container.RegisterInstance <INotificationManager>(notificationManager);

            IEmailNotificationSendingGateway emailNotificationSendingGateway = null;

            var emailNotificationSendingGatewayName = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Notifications:Gateway", "Default");

            if (string.Equals(emailNotificationSendingGatewayName, "Default", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new DefaultSmtpEmailNotificationSendingGateway(settingsManager);
            }
            else if (string.Equals(emailNotificationSendingGatewayName, "SendGrid", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new SendGridEmailNotificationSendingGateway(settingsManager);
            }

            if (emailNotificationSendingGateway != null)
            {
                container.RegisterInstance(emailNotificationSendingGateway);
            }

            var defaultSmsNotificationSendingGateway = new DefaultSmsNotificationSendingGateway();
            container.RegisterInstance <ISmsNotificationSendingGateway>(defaultSmsNotificationSendingGateway);

            #endregion

            #region Assets

            var blobConnectionString = BlobConnectionString.Parse(ConfigurationManager.ConnectionStrings["AssetsConnectionString"].ConnectionString);

            if (string.Equals(blobConnectionString.Provider, FileSystemBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var fileSystemBlobProvider = new FileSystemBlobProvider(NormalizePath(blobConnectionString.RootPath), blobConnectionString.PublicUrl);

                container.RegisterInstance <IBlobStorageProvider>(fileSystemBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(fileSystemBlobProvider);
            }
            else if (string.Equals(blobConnectionString.Provider, AzureBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var azureBlobProvider = new AzureBlobProvider(blobConnectionString.ConnectionString);
                container.RegisterInstance <IBlobStorageProvider>(azureBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(azureBlobProvider);
            }


            #endregion

            #region Modularity

            var modulesDataSources    = ConfigurationManager.AppSettings.SplitStringValue("VirtoCommerce:ModulesDataSources");
            var externalModuleCatalog = new ExternalManifestModuleCatalog(moduleCatalog.Modules, modulesDataSources, container.Resolve <ILog>());
            container.RegisterType <ModulesController>(new InjectionConstructor(externalModuleCatalog, new ModuleInstaller(modulesPath, externalModuleCatalog), notifier, container.Resolve <IUserNameResolver>(), settingsManager));

            #endregion

            #region ChangeLogging

            var changeLogService = new ChangeLogService(platformRepositoryFactory);
            container.RegisterInstance <IChangeLogService>(changeLogService);

            #endregion

            #region Security
            container.RegisterInstance <IPermissionScopeService>(new PermissionScopeService());
            container.RegisterType <IRoleManagementService, RoleManagementService>(new ContainerControlledLifetimeManager());

            var apiAccountProvider = new ApiAccountProvider(platformRepositoryFactory, cacheManager);
            container.RegisterInstance <IApiAccountProvider>(apiAccountProvider);

            container.RegisterType <IClaimsIdentityProvider, ApplicationClaimsIdentityProvider>(new ContainerControlledLifetimeManager());

            container.RegisterInstance(app.GetDataProtectionProvider());
            container.RegisterType <SecurityDbContext>(new InjectionConstructor(connectionStringName));
            container.RegisterType <IUserStore <ApplicationUser>, ApplicationUserStore>();
            container.RegisterType <IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
            container.RegisterType <ApplicationUserManager>();
            container.RegisterType <ApplicationSignInManager>();

            var nonEditableUsers = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:NonEditableUsers", string.Empty);
            container.RegisterInstance <ISecurityOptions>(new SecurityOptions(nonEditableUsers));

            container.RegisterType <ISecurityService, SecurityService>();

            #endregion

            #region ExportImport
            container.RegisterType <IPlatformExportImportManager, PlatformExportImportManager>();
            #endregion

            #region Serialization

            container.RegisterType <IExpressionSerializer, XmlExpressionSerializer>();

            #endregion
        }
        public virtual async Task InitializeDbAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
        {
            var jobStorage        = serviceProvider.GetService <JobStorage>();
            var newHangfireServer = jobStorage != null && jobStorage.GetType() != typeof(NoopJobStorage);

            if (newHangfireServer)
            {
                var configuration = serviceProvider.GetRequiredService <HangfireConfiguration>();

                //Initialize Hangfire Db
                if (!string.IsNullOrEmpty(configuration.ConnectionString))
                {
                    if (configuration.DbInitialiation == DbInitialiation.PrepareSchemaIfNecessary)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ConnectionString, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ExistingConnection, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.PrepareSchemaIfNecessaryAndHeavyMigrations)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureTablesDeletedThenEnsureDbAndTablesCreated)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureTablesDeletedAsync(configuration.ConnectionString, configuration.SchemaName);

                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureTablesDeletedAsync(configuration.ExistingConnection, configuration.SchemaName);

                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureDbAndTablesCreated)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureDbAndTablesCreatedAndHeavyMigrations)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                }

                //Launch Server
                var applicationLifetime = serviceProvider.GetRequiredService <IApplicationLifetime>();
                var additionalProcesses = serviceProvider.GetServices <IBackgroundProcess>();
                var setter        = serviceProvider.GetRequiredService <Action <IBackgroundProcessingServer> >();
                var serverDetails = HangfireLauncher.StartHangfireServer(serviceProvider.GetRequiredService <BackgroundJobServerOptions>(), jobStorage, new HangfireLauncherOptions()
                {
                    ApplicationLifetime = applicationLifetime, AdditionalProcesses = additionalProcesses
                });
                setter(serverDetails.Server);
            }
        }
예제 #9
0
        private static void InitializePlatform(IAppBuilder app, IUnityContainer container, string connectionStringName, HangfireLauncher hangfireLauncher, string modulesPath)
        {
            container.RegisterType <ICurrentUser, CurrentUser>(new HttpContextLifetimeManager());
            container.RegisterType <IUserNameResolver, UserNameResolver>();

            #region Setup database

            using (var db = new SecurityDbContext(connectionStringName))
            {
                new IdentityDatabaseInitializer().InitializeDatabase(db);
            }

            using (var context = new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor()))
            {
                new PlatformDatabaseInitializer().InitializeDatabase(context);
            }

            hangfireLauncher.ConfigureDatabase();

            #endregion

            Func <IPlatformRepository> platformRepositoryFactory = () => new PlatformRepository(connectionStringName, container.Resolve <AuditableInterceptor>(), new EntityPrimaryKeyGeneratorInterceptor());
            container.RegisterType <IPlatformRepository>(new InjectionFactory(c => platformRepositoryFactory()));
            container.RegisterInstance(platformRepositoryFactory);
            var moduleCatalog = container.Resolve <IModuleCatalog>();

            #region Caching

            //Cure for System.Runtime.Caching.MemoryCache freezing
            //https://www.zpqrtbnk.net/posts/appdomains-threads-cultureinfos-and-paracetamol
            app.SanitizeThreadCulture();
            ICacheManager <object> cacheManager = null;

            //Try to load cache configuration from web.config first
            //Should be aware to using Web cache cache handle because it not worked in native threads. (Hangfire jobs)
            var cacheManagerSection = ConfigurationManager.GetSection(CacheManagerSection.DefaultSectionName) as CacheManagerSection;
            if (cacheManagerSection != null && cacheManagerSection.CacheManagers.Any(p => p.Name.EqualsInvariant("platformCache")))
            {
                var configuration = ConfigurationBuilder.LoadConfiguration("platformCache") as CacheManagerConfiguration;

                if (configuration != null)
                {
                    configuration.LoggerFactoryType          = typeof(CacheManagerLoggerFactory);
                    configuration.LoggerFactoryTypeArguments = new[] { container.Resolve <ILog>() };
                    cacheManager = CacheFactory.FromConfiguration <object>(configuration);
                }
            }
            if (cacheManager == null)
            {
                cacheManager = CacheFactory.Build("platformCache", settings =>
                {
                    settings.WithUpdateMode(CacheUpdateMode.Up)
                    .WithSystemRuntimeCacheHandle("memCacheHandle")
                    .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromMinutes(5));
                });
            }

            container.RegisterInstance(cacheManager);

            #endregion

            #region Settings

            var platformModuleManifest = new ModuleManifest
            {
                Id              = "VirtoCommerce.Platform",
                Version         = PlatformVersion.CurrentVersion.ToString(),
                PlatformVersion = PlatformVersion.CurrentVersion.ToString(),
                Settings        = new[]
                {
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendGrid",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendGrid.ApiKey",
                                ValueType   = ModuleSetting.TypeSecureString,
                                Title       = "SendGrid API key",
                                Description = "Your SendGrid API key"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SendingJob",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SendingJob.TakeCount",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Job Take Count",
                                Description = "Take count for sending job"
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Notifications|SmtpClient",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Host",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server host",
                                Description = "Smtp server host"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Port",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Smtp server port",
                                Description = "Smtp server port"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Login",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Smtp server login",
                                Description = "Smtp server login"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.Password",
                                ValueType   = ModuleSetting.TypeSecureString,
                                Title       = "Smtp server password",
                                Description = "Smtp server password"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.Notifications.SmptClient.UseSsl",
                                ValueType   = ModuleSetting.TypeBoolean,
                                Title       = "Use SSL",
                                Description = "Use secure connection"
                            },
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|Security",
                        Settings = new []
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.Security.AccountTypes",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Account types",
                                Description  = "Dictionary for possible account types",
                                IsArray      = true,
                                ArrayValues  = Enum.GetNames(typeof(AccountType)),
                                DefaultValue = AccountType.Manager.ToString()
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Profile",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name      = "VirtoCommerce.Platform.UI.MainMenu.State",
                                ValueType = ModuleSetting.TypeJson,
                                Title     = "Persisted state of main menu"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Language",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Language",
                                Description  = "Default language (two letter code from ISO 639-1, case-insensitive). Example: en, de",
                                DefaultValue = "en"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.RegionalFormat",
                                ValueType    = ModuleSetting.TypeString,
                                Title        = "Regional format",
                                Description  = "Default regional format (CLDR locale code, with dash or underscore as delemiter, case-insensitive). Example: en, en_US, sr_Cyrl, sr_Cyrl_RS",
                                DefaultValue = "en"
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.UI.TimeZone",
                                ValueType   = ModuleSetting.TypeString,
                                Title       = "Time zone",
                                Description = "Default time zone (IANA time zone name [tz database], exactly as in database, case-sensitive). Examples: America/New_York, Europe/Moscow"
                            },
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.UseTimeAgo",
                                ValueType    = ModuleSetting.TypeBoolean,
                                Title        = "Use time ago format when is possible",
                                Description  = "When set to true (by default), system will display date in format like 'a few seconds ago' when possible",
                                DefaultValue = true.ToString()
                            },
                            new ModuleSetting
                            {
                                Name        = "VirtoCommerce.Platform.UI.FullDateThreshold",
                                ValueType   = ModuleSetting.TypeInteger,
                                Title       = "Full date threshold",
                                Description = "Number of units after time ago format will be switched to full date format"
                            },
                            new ModuleSetting
                            {
                                Name          = "VirtoCommerce.Platform.UI.FullDateThresholdUnit",
                                ValueType     = ModuleSetting.TypeString,
                                Title         = "Full date threshold unit",
                                Description   = "Unit of full date threshold",
                                DefaultValue  = "Never",
                                AllowedValues = new[]
                                {
                                    "Never",
                                    "Seconds",
                                    "Minutes",
                                    "Hours",
                                    "Days",
                                    "Weeks",
                                    "Months",
                                    "Quarters",
                                    "Years"
                                }
                            }
                        }
                    },
                    new ModuleSettingsGroup
                    {
                        Name     = "Platform|User Interface",
                        Settings = new[]
                        {
                            new ModuleSetting
                            {
                                Name         = "VirtoCommerce.Platform.UI.Customization",
                                ValueType    = ModuleSetting.TypeJson,
                                Title        = "Customization",
                                Description  = "JSON contains personalization settings of manager UI",
                                DefaultValue = "{\n" +
                                               "  \"title\": \"Virto Commerce\",\n" +
                                               "  \"logo\": \"Content/themes/main/images/logo.png\",\n" +
                                               "  \"contrast_logo\": \"Content/themes/main/images/contrast-logo.png\"\n" +
                                               "}"
                            }
                        }
                    }
                }
            };

            var settingsManager = new SettingsManager(moduleCatalog, platformRepositoryFactory, cacheManager, new[] { new ManifestModuleInfo(platformModuleManifest) });
            container.RegisterInstance <ISettingsManager>(settingsManager);

            #endregion

            #region Dynamic Properties

            container.RegisterType <IDynamicPropertyService, DynamicPropertyService>(new ContainerControlledLifetimeManager());

            #endregion

            #region Notifications

            var hubSignalR = GlobalHost.ConnectionManager.GetHubContext <ClientPushHub>();
            var notifier   = new InMemoryPushNotificationManager(hubSignalR);
            container.RegisterInstance <IPushNotificationManager>(notifier);

            var resolver = new LiquidNotificationTemplateResolver();
            container.RegisterInstance <INotificationTemplateResolver>(resolver);

            var notificationTemplateService = new NotificationTemplateServiceImpl(platformRepositoryFactory);
            container.RegisterInstance <INotificationTemplateService>(notificationTemplateService);

            var notificationManager = new NotificationManager(resolver, platformRepositoryFactory, notificationTemplateService);
            container.RegisterInstance <INotificationManager>(notificationManager);

            IEmailNotificationSendingGateway emailNotificationSendingGateway = null;

            var emailNotificationSendingGatewayName = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:Notifications:Gateway", "Default");

            if (string.Equals(emailNotificationSendingGatewayName, "Default", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new DefaultSmtpEmailNotificationSendingGateway(settingsManager);
            }
            else if (string.Equals(emailNotificationSendingGatewayName, "SendGrid", StringComparison.OrdinalIgnoreCase))
            {
                emailNotificationSendingGateway = new SendGridEmailNotificationSendingGateway(settingsManager);
            }

            if (emailNotificationSendingGateway != null)
            {
                container.RegisterInstance(emailNotificationSendingGateway);
            }

            var defaultSmsNotificationSendingGateway = new DefaultSmsNotificationSendingGateway();
            container.RegisterInstance <ISmsNotificationSendingGateway>(defaultSmsNotificationSendingGateway);

            #endregion

            #region Assets

            var blobConnectionString = BlobConnectionString.Parse(ConfigurationManager.ConnectionStrings["AssetsConnectionString"].ConnectionString);

            if (string.Equals(blobConnectionString.Provider, FileSystemBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var fileSystemBlobProvider = new FileSystemBlobProvider(NormalizePath(blobConnectionString.RootPath), blobConnectionString.PublicUrl);

                container.RegisterInstance <IBlobStorageProvider>(fileSystemBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(fileSystemBlobProvider);
            }
            else if (string.Equals(blobConnectionString.Provider, AzureBlobProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
            {
                var azureBlobProvider = new AzureBlobProvider(blobConnectionString.ConnectionString);
                container.RegisterInstance <IBlobStorageProvider>(azureBlobProvider);
                container.RegisterInstance <IBlobUrlResolver>(azureBlobProvider);
            }


            #endregion

            #region Modularity

            var modulesDataSources    = ConfigurationManager.AppSettings.SplitStringValue("VirtoCommerce:ModulesDataSources");
            var externalModuleCatalog = new ExternalManifestModuleCatalog(moduleCatalog.Modules, modulesDataSources, container.Resolve <ILog>());
            container.RegisterType <ModulesController>(new InjectionConstructor(externalModuleCatalog, new ModuleInstaller(modulesPath, externalModuleCatalog), notifier, container.Resolve <IUserNameResolver>(), settingsManager));

            #endregion

            #region ChangeLogging

            var changeLogService = new ChangeLogService(platformRepositoryFactory);
            container.RegisterInstance <IChangeLogService>(changeLogService);

            #endregion

            #region Security
            container.RegisterInstance <IPermissionScopeService>(new PermissionScopeService());
            container.RegisterType <IRoleManagementService, RoleManagementService>(new ContainerControlledLifetimeManager());

            var apiAccountProvider = new ApiAccountProvider(platformRepositoryFactory, cacheManager);
            container.RegisterInstance <IApiAccountProvider>(apiAccountProvider);

            container.RegisterType <IClaimsIdentityProvider, ApplicationClaimsIdentityProvider>(new ContainerControlledLifetimeManager());

            container.RegisterInstance(app.GetDataProtectionProvider());
            container.RegisterType <SecurityDbContext>(new InjectionConstructor(connectionStringName));
            container.RegisterType <IUserStore <ApplicationUser>, ApplicationUserStore>();
            container.RegisterType <IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
            container.RegisterType <ApplicationUserManager>();
            container.RegisterType <ApplicationSignInManager>();

            var nonEditableUsers = ConfigurationManager.AppSettings.GetValue("VirtoCommerce:NonEditableUsers", string.Empty);
            container.RegisterInstance <ISecurityOptions>(new SecurityOptions(nonEditableUsers));

            container.RegisterType <ISecurityService, SecurityService>();

            #endregion

            #region ExportImport
            container.RegisterType <IPlatformExportImportManager, PlatformExportImportManager>();
            #endregion

            #region Serialization

            container.RegisterType <IExpressionSerializer, XmlExpressionSerializer>();

            #endregion
        }