/// <summary> /// Called early in the filter pipeline to confirm request is authorized /// </summary> /// <param name="context">Authorization filter context</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task CheckAccessPublicStoreAsync(AuthorizationFilterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //check whether this filter has been overridden for the Action var actionFilter = context.ActionDescriptor.FilterDescriptors .Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action) .Select(filterDescriptor => filterDescriptor.Filter) .OfType <CheckAccessPublicStoreAttribute>() .FirstOrDefault(); //ignore filter (the action is available even if navigation is not allowed) if (actionFilter?.IgnoreFilter ?? _ignoreFilter) { return; } //check whether current customer has access to a public store if (await _permissionService.AuthorizeAsync(StandardPermissionProvider.PublicStoreAllowNavigation)) { return; } //customer hasn't access to a public store context.Result = new ChallengeResult(); }
/// <summary> /// Add and configure WebMarkupMin service /// </summary> /// <param name="services">Collection of service descriptors</param> public static void AddNopWebMarkupMin(this IServiceCollection services) { //check whether database is installed if (!DataSettingsManager.IsDatabaseInstalled()) { return; } services .AddWebMarkupMin(options => { options.AllowMinificationInDevelopmentEnvironment = true; options.AllowCompressionInDevelopmentEnvironment = true; options.DisableMinification = !EngineContext.Current.Resolve <CommonSettings>().EnableHtmlMinification; options.DisableCompression = true; options.DisablePoweredByHttpHeaders = true; }) .AddHtmlMinification(options => { options.CssMinifierFactory = new NUglifyCssMinifierFactory(); options.JsMinifierFactory = new NUglifyJsMinifierFactory(); }) .AddXmlMinification(options => { var settings = options.MinificationSettings; settings.RenderEmptyTagsWithSpace = true; settings.CollapseTagsWithoutContent = true; }); }
/// <summary> /// Called early in the filter pipeline to confirm request is authorized /// </summary> /// <param name="context">Authorization filter context</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task AuthorizeAdminAsync(AuthorizationFilterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //check whether this filter has been overridden for the action var actionFilter = context.ActionDescriptor.FilterDescriptors .Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action) .Select(filterDescriptor => filterDescriptor.Filter) .OfType <AuthorizeAdminAttribute>() .FirstOrDefault(); //ignore filter (the action is available even if a customer hasn't access to the admin area) if (actionFilter?.IgnoreFilter ?? _ignoreFilter) { return; } //there is AdminAuthorizeFilter, so check access if (context.Filters.Any(filter => filter is AuthorizeAdminFilter)) { //authorize permission of access to the admin area if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.AccessAdminPanel)) { context.Result = new ChallengeResult(); } } }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task SaveLastActivityAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } //only in GET requests if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Get, StringComparison.InvariantCultureIgnoreCase)) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //update last activity date var customer = await _workContext.GetCurrentCustomerAsync(); if (customer.LastActivityDateUtc.AddMinutes(_customerSettings.LastActivityMinutes) < DateTime.UtcNow) { customer.LastActivityDateUtc = DateTime.UtcNow; //update customer without event notification await _customerRepository.UpdateAsync(customer, false); } }
public static void StartEngine(this IApplicationBuilder application) { var engine = EngineContext.Current; //further actions are performed only when the database is installed if (DataSettingsManager.IsDatabaseInstalled()) { //initialize and start schedule tasks Services.Tasks.TaskManager.Instance.Initialize(); Services.Tasks.TaskManager.Instance.Start(); //log application start engine.Resolve <ILogger>().InformationAsync("Application started").Wait(); //install and update plugins var pluginService = engine.Resolve <IPluginService>(); pluginService.InstallPluginsAsync().Wait(); pluginService.UpdatePluginsAsync().Wait(); //update nopCommerce core and db var migrationManager = engine.Resolve <IMigrationManager>(); var assembly = Assembly.GetAssembly(typeof(ApplicationBuilderExtensions)); migrationManager.ApplyUpMigrations(assembly, true); assembly = Assembly.GetAssembly(typeof(IMigrationManager)); migrationManager.ApplyUpMigrations(assembly, true); #if DEBUG //prevent save the update migrations into the DB during the developing process var versions = EngineContext.Current.Resolve <IRepository <MigrationVersionInfo> >(); versions.DeleteAsync(mvi => mvi.Description.StartsWith(string.Format(NopMigrationDefaults.UpdateMigrationDescriptionPrefix, NopVersion.FULL_VERSION))); #endif } }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task ValidateAuthenticationForceAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //validate only for registered customers var customer = await _workContext.GetCurrentCustomerAsync(); if (!await _customerService.IsRegisteredAsync(customer)) { return; } //don't validate on the 'Multi-factor authentication settings' page var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; var actionName = actionDescriptor?.ActionName; var controllerName = actionDescriptor?.ControllerName; if (string.IsNullOrEmpty(actionName) || string.IsNullOrEmpty(controllerName)) { return; } if (controllerName.Equals("Customer", StringComparison.InvariantCultureIgnoreCase) && actionName.Equals("MultiFactorAuthentication", StringComparison.InvariantCultureIgnoreCase)) { return; } //whether the feature is enabled if (!_multiFactorAuthenticationSettings.ForceMultifactorAuthentication || !await _multiFactorAuthenticationPluginManager.HasActivePluginsAsync()) { return; } //check selected provider of MFA var selectedProvider = await _genericAttributeService .GetAttributeAsync <string>(customer, NopCustomerDefaults.SelectedMultiFactorAuthenticationProviderAttribute); if (!string.IsNullOrEmpty(selectedProvider)) { return; } //redirect to MultiFactorAuthenticationSettings page if force is enabled context.Result = new RedirectToRouteResult("MultiFactorAuthenticationSettings", null); }
/// <summary> /// Configure the request localization feature /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public static void UseNopRequestLocalization(this IApplicationBuilder application) { application.UseRequestLocalization(async options => { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //prepare supported cultures var cultures = (await EngineContext.Current.Resolve <ILanguageService>().GetAllLanguagesAsync()) .OrderBy(language => language.DisplayOrder) .Select(language => new CultureInfo(language.LanguageCulture)).ToList(); options.SupportedCultures = cultures; options.SupportedUICultures = cultures; options.DefaultRequestCulture = new RequestCulture(cultures.FirstOrDefault()); options.ApplyCurrentCultureToResponseHeaders = true; //configure culture providers options.AddInitialRequestCultureProvider(new NopSeoUrlCultureProvider()); var cookieRequestCultureProvider = options.RequestCultureProviders.OfType <CookieRequestCultureProvider>().FirstOrDefault(); if (cookieRequestCultureProvider is not null) { cookieRequestCultureProvider.CookieName = $"{NopCookieDefaults.Prefix}{NopCookieDefaults.CultureCookie}"; } }); }
public static void StartEngine(this IApplicationBuilder application) { var engine = EngineContext.Current; //further actions are performed only when the database is installed if (DataSettingsManager.IsDatabaseInstalled()) { //log application start engine.Resolve <ILogger>().InformationAsync("Application started").Wait(); //install and update plugins var pluginService = engine.Resolve <IPluginService>(); pluginService.InstallPluginsAsync().Wait(); pluginService.UpdatePluginsAsync().Wait(); //update nopCommerce core and db var migrationManager = engine.Resolve <IMigrationManager>(); var assembly = Assembly.GetAssembly(typeof(ApplicationBuilderExtensions)); migrationManager.ApplyUpMigrations(assembly, MigrationProcessType.Update); assembly = Assembly.GetAssembly(typeof(IMigrationManager)); migrationManager.ApplyUpMigrations(assembly, MigrationProcessType.Update); var taskScheduler = engine.Resolve <ITaskScheduler>(); taskScheduler.InitializeAsync().Wait(); taskScheduler.StartScheduler(); } }
/// <summary> /// Collect the UP migration expressions /// </summary> public override void Up() { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //locales var languages = _languageService.GetAllLanguagesAsync(true).Result; var languageId = languages .FirstOrDefault(lang => lang.UniqueSeoCode == new CultureInfo(NopCommonDefaults.DefaultLanguageCulture).TwoLetterISOLanguageName) ?.Id; _localizationService.AddOrUpdateLocaleResourceAsync(new Dictionary <string, string> { ["Plugins.Payments.PayPalCommerce.Fields.DisplayPayLaterMessages"] = "Display Pay Later messages", ["Plugins.Payments.PayPalCommerce.Fields.DisplayPayLaterMessages.Hint"] = "Determine whether to display Pay Later messages. This message displays how much the customer pays in four payments. The message will be shown next to the PayPal buttons.", }, languageId).Wait(); //settings if (!_settingService.SettingExistsAsync(_payPalCommerceSettings, settings => settings.DisplayPayLaterMessages).Result) { _payPalCommerceSettings.DisplayPayLaterMessages = false; } _settingService.SaveSettingAsync(_payPalCommerceSettings).Wait(); }
/// <summary>Collect the UP migration expressions</summary> public override void Up() { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //do not use DI, because it produces exception on the installation process var settingRepository = EngineContext.Current.Resolve <IRepository <Setting> >(); var settingService = EngineContext.Current.Resolve <ISettingService>(); //miniprofiler settings are moved to appSettings settingRepository .DeleteAsync(setting => setting.Name == "storeinformationsettings.displayminiprofilerforadminonly" || setting.Name == "storeinformationsettings.displayminiprofilerinpublicstore").Wait(); //#4363 var commonSettings = settingService.LoadSettingAsync <CommonSettings>().Result; if (!settingService.SettingExistsAsync(commonSettings, settings => settings.ClearLogOlderThanDays).Result) { commonSettings.ClearLogOlderThanDays = 0; settingService.SaveSettingAsync(commonSettings).Wait(); } }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task ValidateCaptchaAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //whether CAPTCHA is enabled if (_captchaSettings.Enabled && context.HttpContext?.Request != null) { //push the validation result as an action parameter var isValid = false; //get form values var captchaResponseValue = context.HttpContext.Request.Form[RESPONSE_FIELD_KEY]; var gCaptchaResponseValue = context.HttpContext.Request.Form[G_RESPONSE_FIELD_KEY]; if (!StringValues.IsNullOrEmpty(captchaResponseValue) || !StringValues.IsNullOrEmpty(gCaptchaResponseValue)) { //validate request try { var value = !StringValues.IsNullOrEmpty(captchaResponseValue) ? captchaResponseValue : gCaptchaResponseValue; var response = await _captchaHttpClient.ValidateCaptchaAsync(value); switch (_captchaSettings.CaptchaType) { case CaptchaType.CheckBoxReCaptchaV2: isValid = response.IsValid; break; case CaptchaType.ReCaptchaV3: isValid = response.IsValid && response.Action == context.RouteData.Values["action"].ToString() && response.Score > _captchaSettings.ReCaptchaV3ScoreThreshold; break; default: break; } } catch (Exception exception) { await _logger.ErrorAsync("Error occurred on CAPTCHA validation", exception, await _workContext.GetCurrentCustomerAsync()); } } context.ActionArguments[_actionParameterName] = isValid; } else { context.ActionArguments[_actionParameterName] = false; } }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task CheckLanguageSeoCodeAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } //only in GET requests if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Get, StringComparison.InvariantCultureIgnoreCase)) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //check whether this filter has been overridden for the Action var actionFilter = context.ActionDescriptor.FilterDescriptors .Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action) .Select(filterDescriptor => filterDescriptor.Filter) .OfType <CheckLanguageSeoCodeAttribute>() .FirstOrDefault(); //ignore filter (an action doesn't need to be checked) if (actionFilter?.IgnoreFilter ?? _ignoreFilter) { return; } //whether SEO friendly URLs are enabled if (!_localizationSettings.SeoFriendlyUrlsForLanguagesEnabled) { return; } //check whether current page URL is already localized URL var pageUrl = _webHelper.GetRawUrl(context.HttpContext.Request); var result = await pageUrl.IsLocalizedUrlAsync(context.HttpContext.Request.PathBase, true); if (result.IsLocalized) { return; } //not localized yet, so redirect to the page with working language SEO code var language = await _workContext.GetWorkingLanguageAsync(); pageUrl = pageUrl.AddLanguageSeoCodeToUrl(context.HttpContext.Request.PathBase, true, language); context.Result = new LocalRedirectResult(pageUrl, false); }
/// <summary> /// Invoke middleware actions /// </summary> /// <param name="context">HTTP context</param> /// <returns>A task that represents the asynchronous operation</returns> public async Task InvokeAsync(HttpContext context) { context.Features.Set <IAuthenticationFeature>(new AuthenticationFeature { OriginalPath = context.Request.Path, OriginalPathBase = context.Request.PathBase }); // Give any IAuthenticationRequestHandler schemes a chance to handle the request var handlers = EngineContext.Current.Resolve <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { try { if (await handlers.GetHandlerAsync(context, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { return; } } catch (Exception ex) { if (!DataSettingsManager.IsDatabaseInstalled()) { continue; } var externalAuthenticationSettings = EngineContext.Current.Resolve <ExternalAuthenticationSettings>(); if (!externalAuthenticationSettings.LogErrors) { continue; } var logger = EngineContext.Current.Resolve <ILogger>(); await logger.ErrorAsync(ex.Message, ex); } } var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await context.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { context.User = result.Principal; } } await _next(context); }
/// <summary> /// Adds the authentication middleware, which enables authentication capabilities. /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public static void UseNopAuthentication(this IApplicationBuilder application) { //check whether database is installed if (!DataSettingsManager.IsDatabaseInstalled()) { return; } application.UseMiddleware <AuthenticationMiddleware>(); }
/// <summary> /// Configure WebMarkupMin /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public static void UseNopWebMarkupMin(this IApplicationBuilder application) { //check whether database is installed if (!DataSettingsManager.IsDatabaseInstalled()) { return; } application.UseWebMarkupMin(); }
/// <summary> /// Register routes /// </summary> /// <param name="endpointRouteBuilder">Route builder</param> public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder) { var pattern = GetLanguageRoutePattern(); pattern += "/"; //default routes //these routes are not generic, they are just default to map requests that don't match other patterns, //but we define them here since this route provider is with the lowest priority, to allow to add additional routes before them endpointRouteBuilder.MapControllerRoute(name: "Default", pattern: $"{pattern}{{controller=Home}}/{{action=Index}}/{{id?}}"); endpointRouteBuilder.MapControllerRoute(name: "Default", pattern: "{controller=Home}/{action=Index}/{id?}"); //generic routes pattern += "{SeName}/"; if (DataSettingsManager.IsDatabaseInstalled()) { endpointRouteBuilder.MapDynamicControllerRoute <SlugRouteTransformer>(pattern); } endpointRouteBuilder.MapControllerRoute(name: "GenericUrl", pattern: "{genericSeName}", new { controller = "Common", action = "GenericUrl" }); endpointRouteBuilder.MapControllerRoute(name: "GenericUrl", pattern: "{genericSeName}/{genericParameter}", new { controller = "Common", action = "GenericUrl" }); endpointRouteBuilder.MapControllerRoute("Product", pattern, new { controller = "Product", action = "ProductDetails" }); endpointRouteBuilder.MapControllerRoute("Category", pattern, new { controller = "Catalog", action = "Category" }); endpointRouteBuilder.MapControllerRoute("Manufacturer", pattern, new { controller = "Catalog", action = "Manufacturer" }); endpointRouteBuilder.MapControllerRoute("Vendor", pattern, new { controller = "Catalog", action = "Vendor" }); endpointRouteBuilder.MapControllerRoute("NewsItem", pattern, new { controller = "News", action = "NewsItem" }); endpointRouteBuilder.MapControllerRoute("BlogPost", pattern, new { controller = "Blog", action = "BlogPost" }); endpointRouteBuilder.MapControllerRoute("Topic", pattern, new { controller = "Topic", action = "TopicDetails" }); endpointRouteBuilder.MapControllerRoute("ProductsByTag", pattern, new { controller = "Catalog", action = "ProductsByTag" }); }
/// <summary> /// Add and configure MVC for the application /// </summary> /// <param name="services">Collection of service descriptors</param> /// <returns>A builder for configuring MVC services</returns> public static IMvcBuilder AddNopMvc(this IServiceCollection services) { //add basic MVC feature var mvcBuilder = services.AddControllersWithViews(); mvcBuilder.AddRazorRuntimeCompilation(); var appSettings = Singleton <AppSettings> .Instance; if (appSettings.CommonConfig.UseSessionStateTempDataProvider) { //use session-based temp data provider mvcBuilder.AddSessionStateTempDataProvider(); } else { //use cookie-based temp data provider mvcBuilder.AddCookieTempDataProvider(options => { options.Cookie.Name = $"{NopCookieDefaults.Prefix}{NopCookieDefaults.TempDataCookie}"; //whether to allow the use of cookies from SSL protected page on the other store pages which are not options.Cookie.SecurePolicy = DataSettingsManager.IsDatabaseInstalled() && EngineContext.Current.Resolve <IStoreContext>().GetCurrentStoreAsync().Result.SslEnabled ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.None; }); } services.AddRazorPages(); //MVC now serializes JSON with camel case names by default, use this code to avoid it mvcBuilder.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()); //add custom display metadata provider mvcBuilder.AddMvcOptions(options => options.ModelMetadataDetailsProviders.Add(new NopMetadataProvider())); //add fluent validation mvcBuilder.AddFluentValidation(configuration => { //register all available validators from Nop assemblies var assemblies = mvcBuilder.PartManager.ApplicationParts .OfType <AssemblyPart>() .Where(part => part.Name.StartsWith("Nop", StringComparison.InvariantCultureIgnoreCase)) .Select(part => part.Assembly); configuration.RegisterValidatorsFromAssemblies(assemblies); //implicit/automatic validation of child properties configuration.ImplicitlyValidateChildProperties = true; }); //register controllers as services, it'll allow to override them mvcBuilder.AddControllersAsServices(); return(mvcBuilder); }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> private void ValidateIpAddress(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //get action and controller names var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; var actionName = actionDescriptor?.ActionName; var controllerName = actionDescriptor?.ControllerName; if (string.IsNullOrEmpty(actionName) || string.IsNullOrEmpty(controllerName)) { return; } //don't validate on the 'Access denied' page if (controllerName.Equals("Security", StringComparison.InvariantCultureIgnoreCase) && actionName.Equals("AccessDenied", StringComparison.InvariantCultureIgnoreCase)) { return; } //get allowed IP addresses var ipAddresses = _securitySettings.AdminAreaAllowedIpAddresses; //there are no restrictions if (ipAddresses == null || !ipAddresses.Any()) { return; } //whether current IP is allowed var currentIp = _webHelper.GetCurrentIpAddress(); if (ipAddresses.Any(ip => ip.Equals(currentIp, StringComparison.InvariantCultureIgnoreCase))) { return; } //redirect to 'Access denied' page context.Result = new RedirectToActionResult("AccessDenied", "Security", context.RouteData.Values); }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task ValidatePasswordAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } //ignore AJAX requests if (_webHelper.IsAjaxRequest(context.HttpContext.Request)) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //get action and controller names var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; var actionName = actionDescriptor?.ActionName; var controllerName = actionDescriptor?.ControllerName; if (string.IsNullOrEmpty(actionName) || string.IsNullOrEmpty(controllerName)) { return; } //don't validate on the 'Change Password' page if (controllerName.Equals("Customer", StringComparison.InvariantCultureIgnoreCase) && actionName.Equals("ChangePassword", StringComparison.InvariantCultureIgnoreCase)) { return; } //check password expiration var customer = await _workContext.GetCurrentCustomerAsync(); if (!await _customerService.IsPasswordExpiredAsync(customer)) { return; } var returnUrl = _webHelper.GetRawUrl(context.HttpContext.Request); //redirect to ChangePassword page if expires context.Result = new RedirectToRouteResult("CustomerChangePassword", new { returnUrl = returnUrl }); }
/// <summary> /// Adds services required for anti-forgery support /// </summary> /// <param name="services">Collection of service descriptors</param> public static void AddAntiForgery(this IServiceCollection services) { //override cookie name services.AddAntiforgery(options => { options.Cookie.Name = $"{NopCookieDefaults.Prefix}{NopCookieDefaults.AntiforgeryCookie}"; //whether to allow the use of anti-forgery cookies from SSL protected page on the other store pages which are not options.Cookie.SecurePolicy = DataSettingsManager.IsDatabaseInstalled() && EngineContext.Current.Resolve <IStoreContext>().GetCurrentStoreAsync().Result.SslEnabled ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.None; }); }
/// <summary> /// Adds services required for application session state /// </summary> /// <param name="services">Collection of service descriptors</param> public static void AddHttpSession(this IServiceCollection services) { services.AddSession(options => { options.Cookie.Name = $"{NopCookieDefaults.Prefix}{NopCookieDefaults.SessionCookie}"; options.Cookie.HttpOnly = true; //whether to allow the use of session values from SSL protected page on the other store pages which are not options.Cookie.SecurePolicy = DataSettingsManager.IsDatabaseInstalled() && EngineContext.Current.Resolve <IStoreContext>().GetCurrentStoreAsync().Result.SslEnabled ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.None; }); }
/// <summary>Collect the UP migration expressions</summary> public override void Up() { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //do not use DI, because it produces exception on the installation process var settingRepository = EngineContext.Current.Resolve <IRepository <Setting> >(); var settingService = EngineContext.Current.Resolve <ISettingService>(); //miniprofiler settings are moved to appSettings settingRepository .DeleteAsync(setting => setting.Name == "storeinformationsettings.displayminiprofilerforadminonly" || setting.Name == "storeinformationsettings.displayminiprofilerinpublicstore").Wait(); //#4363 var commonSettings = settingService.LoadSettingAsync <CommonSettings>().Result; if (!settingService.SettingExistsAsync(commonSettings, settings => settings.ClearLogOlderThanDays).Result) { commonSettings.ClearLogOlderThanDays = 0; settingService.SaveSettingAsync(commonSettings).Wait(); } //#5551 var catalogSettings = settingService.LoadSettingAsync <CatalogSettings>().Result; if (!settingService.SettingExistsAsync(catalogSettings, settings => settings.EnableSpecificationAttributeFiltering).Result) { catalogSettings.EnableSpecificationAttributeFiltering = true; settingService.SaveSettingAsync(catalogSettings).Wait(); } //#5204 var shippingSettings = settingService.LoadSettingAsync <ShippingSettings>().Result; if (!settingService.SettingExistsAsync(shippingSettings, settings => settings.ShippingSorting).Result) { shippingSettings.ShippingSorting = ShippingSortingEnum.Position; settingService.SaveSettingAsync(shippingSettings).Wait(); } //#5698 var orderSettings = settingService.LoadSettingAsync <OrderSettings>().Result; if (!settingService.SettingExistsAsync(orderSettings, settings => settings.DisplayOrderSummary).Result) { orderSettings.DisplayOrderSummary = true; settingService.SaveSettingAsync(orderSettings).Wait(); } }
/// <summary> /// Configure middleware for dynamically compressing HTTP responses /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public static void UseNopResponseCompression(this IApplicationBuilder application) { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //whether to use compression (gzip by default) if (EngineContext.Current.Resolve <CommonSettings>().UseResponseCompression) { application.UseResponseCompression(); } }
/// <summary> /// Adds services required for themes support /// </summary> /// <param name="services">Collection of service descriptors</param> public static void AddThemes(this IServiceCollection services) { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //themes support services.Configure <RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new ThemeableViewLocationExpander()); }); }
/// <summary> /// Get pattern used to detect routes with language code /// </summary> /// <returns></returns> protected string GetLanguageRoutePattern() { if (DataSettingsManager.IsDatabaseInstalled()) { var localizationSettings = EngineContext.Current.Resolve <LocalizationSettings>(); if (localizationSettings.SeoFriendlyUrlsForLanguagesEnabled) { return($"{{{NopPathRouteDefaults.LanguageRouteValue}:maxlength(2):{NopPathRouteDefaults.LanguageParameterTransformer}=en}}"); } } return(string.Empty); }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private void SaveSelectedTab(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } //only in POST requests if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Post, StringComparison.InvariantCultureIgnoreCase)) { return; } //ignore AJAX requests if (_webHelper.IsAjaxRequest(context.HttpContext.Request)) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //check whether this filter has been overridden for the Action var actionFilter = context.ActionDescriptor.FilterDescriptors .Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action) .Select(filterDescriptor => filterDescriptor.Filter) .OfType <SaveSelectedTabAttribute>() .FirstOrDefault(); //ignore filter if (actionFilter?.IgnoreFilter ?? _ignoreFilter) { return; } var persistForTheNextRequest = actionFilter?.PersistForTheNextRequest ?? _persistForTheNextRequest; if (context.Controller is BaseController controller) { controller.SaveSelectedTabName(persistForTheNextRequest: persistForTheNextRequest); } }
/// <summary> /// Called asynchronously before the action, after model binding is complete. /// </summary> /// <param name="context">A context for action filters</param> /// <returns>A task that represents the asynchronous operation</returns> private async Task SaveIpAddressAsync(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.HttpContext.Request == null) { return; } //only in GET requests if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Get, StringComparison.InvariantCultureIgnoreCase)) { return; } if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //check whether we store IP addresses if (!_customerSettings.StoreIpAddresses) { return; } //get current IP address var currentIpAddress = _webHelper.GetCurrentIpAddress(); if (string.IsNullOrEmpty(currentIpAddress)) { return; } //update customer's IP address var customer = await _workContext.GetCurrentCustomerAsync(); if (_workContext.OriginalCustomerIfImpersonated == null && !currentIpAddress.Equals(customer.LastIpAddress, StringComparison.InvariantCultureIgnoreCase)) { customer.LastIpAddress = currentIpAddress; //update customer without event notification await _customerRepository.UpdateAsync(customer, false); } }
/// <summary> /// Collect the UP migration expressions /// </summary> public override void Up() { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //settings if (!_settingService.SettingExistsAsync(_ecbExchangeRateSettings, settings => settings.EcbLink).Result) { _ecbExchangeRateSettings.EcbLink = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; } _settingService.SaveSettingAsync(_ecbExchangeRateSettings).Wait(); }
/// <summary> /// Add exception handling /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public static void UseNopExceptionHandler(this IApplicationBuilder application) { var appSettings = EngineContext.Current.Resolve <AppSettings>(); var webHostEnvironment = EngineContext.Current.Resolve <IWebHostEnvironment>(); var useDetailedExceptionPage = appSettings.Get <CommonConfig>().DisplayFullErrorStack || webHostEnvironment.IsDevelopment(); if (useDetailedExceptionPage) { //get detailed exceptions for developing and testing purposes application.UseDeveloperExceptionPage(); } else { //or use special exception handler application.UseExceptionHandler("/Error/Error"); } //log errors application.UseExceptionHandler(handler => { handler.Run(async context => { var exception = context.Features.Get <IExceptionHandlerFeature>()?.Error; if (exception == null) { return; } try { //check whether database is installed if (DataSettingsManager.IsDatabaseInstalled()) { //get current customer var currentCustomer = await EngineContext.Current.Resolve <IWorkContext>().GetCurrentCustomerAsync(); //log error await EngineContext.Current.Resolve <ILogger>().ErrorAsync(exception.Message, exception, currentCustomer); } } finally { //rethrow the exception to show the error page ExceptionDispatchInfo.Throw(exception); } }); }); }
/// <summary> /// Collect the UP migration expressions /// </summary> public override void Up() { if (!DataSettingsManager.IsDatabaseInstalled()) { return; } //locales var languages = _languageService.GetAllLanguagesAsync(true).Result; var languageId = languages .FirstOrDefault(lang => lang.UniqueSeoCode == new CultureInfo(NopCommonDefaults.DefaultLanguageCulture).TwoLetterISOLanguageName) ?.Id; _localizationService.AddOrUpdateLocaleResourceAsync(new Dictionary <string, string> { ["Plugins.Tax.Avalara.Fields.UseTaxRateTables"] = "Use tax rate tables to estimate ", ["Plugins.Tax.Avalara.Fields.UseTaxRateTables.Hint"] = "Determine whether to use tax rate tables to estimate. This will be used as a default tax calculation for catalog pages and will be adjusted and reconciled to the final transaction tax during checkout. Tax rates are looked up by zip code (US only) in a file that will be periodically updated from the Avalara (see Schedule tasks).", }, languageId).Wait(); //settings if (!_settingService.SettingExistsAsync(_avalaraTaxSettings, settings => settings.UseTaxRateTables).Result) { _avalaraTaxSettings.UseTaxRateTables = true; } _settingService.SaveSettingAsync(_avalaraTaxSettings).Wait(); //in version 4.50 we added the LastEnabledUtc field to the ScheduleTask entity, //we need to make sure that these changes are applied before inserting new task into the database var scheduleTaskTableName = NameCompatibilityManager.GetTableName(typeof(ScheduleTask)); //add column if not exists if (!Schema.Table(scheduleTaskTableName).Column(nameof(ScheduleTask.LastEnabledUtc)).Exists()) { Alter.Table(scheduleTaskTableName) .AddColumn(nameof(ScheduleTask.LastEnabledUtc)).AsDateTime2().Nullable(); } //schedule task Insert.IntoTable(scheduleTaskTableName).Row(new { Enabled = true, LastEnabledUtc = DateTime.UtcNow, Seconds = AvalaraTaxDefaults.DownloadTaxRatesTask.Days * 24 * 60 * 60, StopOnError = false, Name = AvalaraTaxDefaults.DownloadTaxRatesTask.Name, Type = AvalaraTaxDefaults.DownloadTaxRatesTask.Type }); }