using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Net.Http.Headers; using Nop.Core; using Nop.Core.Caching; using Nop.Core.Configuration; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Directory; using Nop.Core.Domain.Orders; using Nop.Core.Domain.Security; using Nop.Core.Domain.Seo; using Nop.Core.Events; using Nop.Core.Infrastructure; using Nop.Data; using Nop.Services.Authentication.External; using Nop.Services.Authentication.MultiFactor; using Nop.Services.Blogs; using Nop.Services.Catalog; using Nop.Services.Cms; using Nop.Services.Common; using Nop.Services.Customers; using Nop.Services.Directory; using Nop.Services.Events; using Nop.Services.Helpers; using Nop.Services.Localization; using Nop.Services.News; using Nop.Services.Orders; using Nop.Services.Payments; using Nop.Services.Plugins; using Nop.Services.Seo; using Nop.Services.Shipping; using Nop.Services.Shipping.Pickup; using Nop.Services.Stores; using Nop.Services.Tax; using Nop.Services.Topics; using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions; using Nop.Web.Areas.Admin.Models.Blogs; using Nop.Web.Areas.Admin.Models.Catalog; using Nop.Web.Areas.Admin.Models.Common; using Nop.Web.Areas.Admin.Models.Localization; using Nop.Web.Areas.Admin.Models.News; using Nop.Web.Areas.Admin.Models.Topics; using Nop.Web.Framework.Models; using Nop.Web.Framework.Models.Extensions; using Nop.Web.Framework.Mvc.Routing; using Nop.Web.Framework.Security; namespace Nop.Web.Areas.Admin.Factories; /// /// Represents common models factory implementation /// public partial class CommonModelFactory : ICommonModelFactory { #region Fields protected readonly AppSettings _appSettings; protected readonly CatalogSettings _catalogSettings; protected readonly CurrencySettings _currencySettings; protected readonly IActionContextAccessor _actionContextAccessor; protected readonly IAuthenticationPluginManager _authenticationPluginManager; protected readonly IBaseAdminModelFactory _baseAdminModelFactory; protected readonly IBlogService _blogService; protected readonly ICategoryService _categoryService; protected readonly ICurrencyService _currencyService; protected readonly ICustomerService _customerService; protected readonly IDateTimeHelper _dateTimeHelper; protected readonly IEventPublisher _eventPublisher; protected readonly IExchangeRatePluginManager _exchangeRatePluginManager; protected readonly IHttpContextAccessor _httpContextAccessor; protected readonly ILanguageService _languageService; protected readonly ILocalizationService _localizationService; protected readonly IMaintenanceService _maintenanceService; protected readonly IManufacturerService _manufacturerService; protected readonly IMeasureService _measureService; protected readonly IMultiFactorAuthenticationPluginManager _multiFactorAuthenticationPluginManager; protected readonly INewsService _newsService; protected readonly INopDataProvider _dataProvider; protected readonly INopFileProvider _fileProvider; protected readonly INopUrlHelper _nopUrlHelper; protected readonly IOrderService _orderService; protected readonly IPaymentPluginManager _paymentPluginManager; protected readonly IPickupPluginManager _pickupPluginManager; protected readonly IPluginService _pluginService; protected readonly IProductService _productService; protected readonly IReturnRequestService _returnRequestService; protected readonly ISearchTermService _searchTermService; protected readonly IServiceCollection _serviceCollection; protected readonly IShippingPluginManager _shippingPluginManager; protected readonly IStaticCacheManager _staticCacheManager; protected readonly IStoreContext _storeContext; protected readonly IStoreService _storeService; protected readonly ITaxPluginManager _taxPluginManager; protected readonly ITopicService _topicService; protected readonly IUrlHelperFactory _urlHelperFactory; protected readonly IUrlRecordService _urlRecordService; protected readonly IWebHelper _webHelper; protected readonly IWidgetPluginManager _widgetPluginManager; protected readonly IWorkContext _workContext; protected readonly MeasureSettings _measureSettings; protected readonly NopHttpClient _nopHttpClient; protected readonly ProxySettings _proxySettings; #endregion #region Ctor public CommonModelFactory(AppSettings appSettings, CatalogSettings catalogSettings, CurrencySettings currencySettings, IActionContextAccessor actionContextAccessor, IAuthenticationPluginManager authenticationPluginManager, IBaseAdminModelFactory baseAdminModelFactory, IBlogService blogService, ICategoryService categoryService, ICurrencyService currencyService, ICustomerService customerService, IDateTimeHelper dateTimeHelper, IEventPublisher eventPublisher, IExchangeRatePluginManager exchangeRatePluginManager, IHttpContextAccessor httpContextAccessor, ILanguageService languageService, ILocalizationService localizationService, IMaintenanceService maintenanceService, IManufacturerService manufacturerService, IMeasureService measureService, IMultiFactorAuthenticationPluginManager multiFactorAuthenticationPluginManager, INewsService newsService, INopDataProvider dataProvider, INopFileProvider fileProvider, INopUrlHelper nopUrlHelper, IOrderService orderService, IPaymentPluginManager paymentPluginManager, IPickupPluginManager pickupPluginManager, IPluginService pluginService, IProductService productService, IReturnRequestService returnRequestService, ISearchTermService searchTermService, IServiceCollection serviceCollection, IShippingPluginManager shippingPluginManager, IStaticCacheManager staticCacheManager, IStoreContext storeContext, IStoreService storeService, ITaxPluginManager taxPluginManager, ITopicService topicService, IUrlHelperFactory urlHelperFactory, IUrlRecordService urlRecordService, IWebHelper webHelper, IWidgetPluginManager widgetPluginManager, IWorkContext workContext, MeasureSettings measureSettings, NopHttpClient nopHttpClient, ProxySettings proxySettings) { _appSettings = appSettings; _catalogSettings = catalogSettings; _currencySettings = currencySettings; _actionContextAccessor = actionContextAccessor; _authenticationPluginManager = authenticationPluginManager; _baseAdminModelFactory = baseAdminModelFactory; _blogService = blogService; _categoryService = categoryService; _currencyService = currencyService; _customerService = customerService; _eventPublisher = eventPublisher; _dataProvider = dataProvider; _dateTimeHelper = dateTimeHelper; _exchangeRatePluginManager = exchangeRatePluginManager; _httpContextAccessor = httpContextAccessor; _languageService = languageService; _localizationService = localizationService; _maintenanceService = maintenanceService; _manufacturerService = manufacturerService; _measureService = measureService; _multiFactorAuthenticationPluginManager = multiFactorAuthenticationPluginManager; _newsService = newsService; _fileProvider = fileProvider; _nopUrlHelper = nopUrlHelper; _orderService = orderService; _paymentPluginManager = paymentPluginManager; _pickupPluginManager = pickupPluginManager; _pluginService = pluginService; _productService = productService; _returnRequestService = returnRequestService; _searchTermService = searchTermService; _serviceCollection = serviceCollection; _shippingPluginManager = shippingPluginManager; _staticCacheManager = staticCacheManager; _storeContext = storeContext; _storeService = storeService; _taxPluginManager = taxPluginManager; _topicService = topicService; _urlHelperFactory = urlHelperFactory; _urlRecordService = urlRecordService; _webHelper = webHelper; _widgetPluginManager = widgetPluginManager; _workContext = workContext; _measureSettings = measureSettings; _nopHttpClient = nopHttpClient; _proxySettings = proxySettings; } #endregion #region Utilities /// /// Prepare store URL warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareStoreUrlWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether current store URL matches the store configured URL var store = await _storeContext.GetCurrentStoreAsync(); var currentStoreUrl = store.Url; if (!string.IsNullOrEmpty(currentStoreUrl) && (currentStoreUrl.Equals(_webHelper.GetStoreLocation(false), StringComparison.InvariantCultureIgnoreCase) || currentStoreUrl.Equals(_webHelper.GetStoreLocation(true), StringComparison.InvariantCultureIgnoreCase))) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.URL.Match") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = string.Format(await _localizationService.GetResourceAsync("Admin.System.Warnings.URL.NoMatch"), currentStoreUrl, _webHelper.GetStoreLocation(false)) }); } /// /// Prepare primary exchange rate currency warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareExchangeRateCurrencyWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether primary exchange rate currency set var primaryExchangeRateCurrency = await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryExchangeRateCurrencyId); if (primaryExchangeRateCurrency == null) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.ExchangeCurrency.NotSet") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.ExchangeCurrency.Set") }); //check whether primary exchange rate currency rate configured if (primaryExchangeRateCurrency.Rate != 1) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.ExchangeCurrency.Rate1") }); } } /// /// Prepare primary store currency warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePrimaryStoreCurrencyWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether primary store currency set var primaryStoreCurrency = await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId); if (primaryStoreCurrency == null) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.PrimaryCurrency.NotSet") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.PrimaryCurrency.Set") }); } /// /// Prepare base weight warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareBaseWeightWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether base measure weight set var baseWeight = await _measureService.GetMeasureWeightByIdAsync(_measureSettings.BaseWeightId); if (baseWeight == null) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultWeight.NotSet") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultWeight.Set") }); //check whether base measure weight ratio configured if (baseWeight.Ratio != 1) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultWeight.Ratio1") }); } } /// /// Prepare base dimension warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareBaseDimensionWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether base measure dimension set var baseDimension = await _measureService.GetMeasureDimensionByIdAsync(_measureSettings.BaseDimensionId); if (baseDimension == null) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultDimension.NotSet") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultDimension.Set") }); //check whether base measure dimension ratio configured if (baseDimension.Ratio != 1) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DefaultDimension.Ratio1") }); } } /// /// Prepare payment methods warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePaymentMethodsWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether payment methods activated if ((await _paymentPluginManager.LoadAllPluginsAsync()).Any()) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.PaymentMethods.OK") }); return; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.PaymentMethods.NoActive") }); } /// /// Prepare performance settings warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePerformanceSettingsWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //check whether "IgnoreStoreLimitations" setting disabled if (!_catalogSettings.IgnoreStoreLimitations && (await _storeService.GetAllStoresAsync()).Count == 1) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Recommendation, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.Performance.IgnoreStoreLimitations") }); } //check whether "IgnoreAcl" setting disabled if (!_catalogSettings.IgnoreAcl) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Recommendation, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.Performance.IgnoreAcl") }); } } /// /// Prepare file permissions warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareFilePermissionsWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); var dirPermissionsOk = true; var dirsToCheck = _fileProvider.GetDirectoriesWrite(); foreach (var dir in dirsToCheck) { if (_fileProvider.CheckPermissions(dir, false, true, true, false)) continue; models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = string.Format(await _localizationService.GetResourceAsync("Admin.System.Warnings.DirectoryPermission.Wrong"), CurrentOSUser.FullName, dir) }); dirPermissionsOk = false; } if (dirPermissionsOk) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.DirectoryPermission.OK") }); } var filePermissionsOk = true; var filesToCheck = _fileProvider.GetFilesWrite(); foreach (var file in filesToCheck) { if (_fileProvider.CheckPermissions(file, false, true, true, true)) continue; models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = string.Format(await _localizationService.GetResourceAsync("Admin.System.Warnings.FilePermission.Wrong"), CurrentOSUser.FullName, file) }); filePermissionsOk = false; } if (filePermissionsOk) { models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.FilePermission.OK") }); } } /// /// Prepare backup file search model /// /// Backup file search model /// Backup file search model protected virtual BackupFileSearchModel PrepareBackupFileSearchModel(BackupFileSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } /// /// Prepare plugins which try to override the same interface warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePluginsOverrideSameInterfaceWarningModelAsync(IList models) { //check whether there are different plugins which try to override the same interface var baseLibraries = new[] { "Nop.Core", "Nop.Data", "Nop.Services", "Nop.Web", "Nop.Web.Framework" }; var overridenServices = _serviceCollection.Where(p => p.ServiceType.FullName != null && p.ServiceType.FullName.StartsWith("Nop.", StringComparison.InvariantCulture) && !p.ServiceType.FullName.StartsWith( typeof(IConsumer<>).FullName?.Replace("~1", string.Empty) ?? string.Empty, StringComparison.InvariantCulture)).Select(p => KeyValuePair.Create(p.ServiceType.FullName, p.ImplementationType?.Assembly.GetName().Name)) .Where(p => baseLibraries.All(library => !p.Value?.StartsWith(library, StringComparison.InvariantCultureIgnoreCase) ?? false)) .GroupBy(p => p.Key, p => p.Value) .Where(p => p.Count() > 1) .ToDictionary(p => p.Key, p => p.ToList()); foreach (var overridenService in overridenServices) { var assemblies = overridenService.Value .Aggregate("", (current, all) => all + ", " + current).TrimEnd(',', ' '); models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = string.Format(await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginsOverrideSameService"), overridenService.Key, assemblies) }); } } /// /// Prepare plugins collision of loaded assembly warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePluginsCollisionsWarningModelAsync(IList models) { var assemblyCollisions = _pluginService.GetAssemblyCollisions(); if (assemblyCollisions.Any()) { var warningFormat = await _localizationService .GetResourceAsync("Admin.System.Warnings.PluginRequiredAssembly"); //check whether there are any collision of loaded assembly foreach (var assembly in _pluginService.GetAssemblyCollisions()) { //get plugin references message var message = assembly.Collisions .Select(item => string.Format(warningFormat, item.PluginName, item.AssemblyVersion)) .Aggregate("", (current, all) => all + ", " + current).TrimEnd(',', ' '); models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = string.Format( await _localizationService.GetResourceAsync("Admin.System.Warnings.AssemblyHasCollision"), assembly.ShortName, assembly.AssemblyInMemory, message) }); } } } /// /// Prepare incompatible plugins warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareIncompatibleWarningModelAsync(IList models) { foreach (var incompatiblePlugin in _pluginService.GetIncompatiblePlugins()) { string warning; switch (incompatiblePlugin.Value) { case PluginIncompatibleType.MainAssemblyNotFound: warning = string.Format( await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginMainAssemblyNotFound"), incompatiblePlugin.Key); break; case PluginIncompatibleType.NotCompatibleWithCurrentVersion: warning = string.Format( await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginNotCompatibleWithCurrentVersion"), incompatiblePlugin.Key); break; default: continue; } models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = warning }); } } /// /// Prepare plugins installed warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePluginsInstalledWarningModelAsync(IList models) { var plugins = await _pluginService.GetPluginDescriptorsAsync(LoadPluginsMode.NotInstalledOnly); var notInstalled = plugins.Select(p => p.FriendlyName).ToList(); if (!notInstalled.Any()) return; models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, DontEncode = true, Text = $"{await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginNotInstalled")}: {string.Join(", ", notInstalled)}. {await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginNotInstalled.HelpText")}" }); } /// /// Prepare plugins enabled warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PreparePluginsEnabledWarningModelAsync(IList models) { var plugins = await _pluginService.GetPluginsAsync(); var notEnabled = new List(); var notEnabledSystemNames = new List(); foreach (var plugin in plugins) { var isEnabled = true; switch (plugin) { case IPaymentMethod paymentMethod: isEnabled = _paymentPluginManager.IsPluginActive(paymentMethod); break; case IShippingRateComputationMethod shippingRateComputationMethod: isEnabled = _shippingPluginManager.IsPluginActive(shippingRateComputationMethod); break; case IPickupPointProvider pickupPointProvider: isEnabled = _pickupPluginManager.IsPluginActive(pickupPointProvider); break; case ITaxProvider taxProvider: isEnabled = _taxPluginManager.IsPluginActive(taxProvider); break; case IExternalAuthenticationMethod externalAuthenticationMethod: isEnabled = _authenticationPluginManager.IsPluginActive(externalAuthenticationMethod); break; case IMultiFactorAuthenticationMethod multiFactorAuthenticationMethod: isEnabled = _multiFactorAuthenticationPluginManager.IsPluginActive(multiFactorAuthenticationMethod); break; case IWidgetPlugin widgetPlugin: isEnabled = _widgetPluginManager.IsPluginActive(widgetPlugin); break; case IExchangeRateProvider exchangeRateProvider: isEnabled = _exchangeRatePluginManager.IsPluginActive(exchangeRateProvider); break; } if (isEnabled) continue; notEnabled.Add(plugin.PluginDescriptor.FriendlyName); notEnabledSystemNames.Add(plugin.PluginDescriptor.SystemName); } if (notEnabled.Any()) { //get URL helper var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext); models.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, DontEncode = true, Text = $"{await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginNotEnabled")}: {string.Join(", ", notEnabled)} ({await _localizationService.GetResourceAsync("Admin.System.Warnings.PluginNotEnabled.AutoFixAndRestart")})" }); } } /// /// Prepare multistore preview models for an entity /// /// Entity type /// Entity /// /// A task that represents the asynchronous operation /// The task result contains the list of multistore preview models for an entity /// protected virtual async Task> PrepareMultistorePreviewModelsForEntityAsync(TEntity entity) where TEntity : BaseEntity, ISlugSupported { var models = new List(); var seName = await _urlRecordService.GetSeNameAsync(entity, ensureTwoPublishedLanguages: false); var stores = await _storeService.GetAllStoresAsync(); foreach (var store in stores) { if (!Uri.TryCreate(store.Url, UriKind.Absolute, out var url)) continue; models.Add(new MultistorePreviewModel { StoreName = store.Name, Url = await _nopUrlHelper .RouteGenericUrlAsync(new { SeName = seName }, url.Scheme, url.IsDefaultPort ? url.Host : $"{url.Host}:{url.Port}"), }); } return models; } #endregion #region Methods /// /// Prepare system info model /// /// System info model /// /// A task that represents the asynchronous operation /// The task result contains the system info model /// public virtual async Task PrepareSystemInfoModelAsync(SystemInfoModel model) { ArgumentNullException.ThrowIfNull(model); model.NopVersion = NopVersion.FULL_VERSION; model.ServerTimeZone = TimeZoneInfo.Local.StandardName; model.ServerLocalTime = DateTime.Now; model.UtcTime = DateTime.UtcNow; model.CurrentUserTime = await _dateTimeHelper.ConvertToUserTimeAsync(DateTime.Now); model.HttpHost = _httpContextAccessor.HttpContext.Request.Headers[HeaderNames.Host]; //ensure no exception is thrown try { model.OperatingSystem = Environment.OSVersion.VersionString; model.AspNetInfo = RuntimeInformation.FrameworkDescription; model.IsFullTrust = AppDomain.CurrentDomain.IsFullyTrusted; } catch { // ignored } foreach (var header in _httpContextAccessor.HttpContext.Request.Headers) { if (header.Key != HeaderNames.Cookie) model.Headers.Add(new SystemInfoModel.HeaderModel { Name = header.Key, Value = header.Value }); } foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { var loadedAssemblyModel = new SystemInfoModel.LoadedAssembly { FullName = assembly.FullName }; //ensure no exception is thrown try { loadedAssemblyModel.Location = assembly.IsDynamic ? null : assembly.Location; loadedAssemblyModel.IsDebug = assembly.GetCustomAttributes(typeof(DebuggableAttribute), false) .FirstOrDefault() is DebuggableAttribute attribute && attribute.IsJITOptimizerDisabled; //https://stackoverflow.com/questions/2050396/getting-the-date-of-a-net-assembly //we use a simple method because the more Jeff Atwood's solution doesn't work anymore //more info at https://blog.codinghorror.com/determining-build-date-the-hard-way/ loadedAssemblyModel.BuildDate = assembly.IsDynamic ? null : (DateTime?)TimeZoneInfo.ConvertTimeFromUtc(_fileProvider.GetLastWriteTimeUtc(assembly.Location), TimeZoneInfo.Local); } catch { // ignored } model.LoadedAssemblies.Add(loadedAssemblyModel); } var currentStaticCacheManagerName = _staticCacheManager.GetType().Name; if (_appSettings.Get().Enabled) currentStaticCacheManagerName += $"({await _localizationService.GetLocalizedEnumAsync(_appSettings.Get().DistributedCacheType)})"; model.CurrentStaticCacheManager = currentStaticCacheManagerName; model.AzureBlobStorageEnabled = _appSettings.Get().Enabled; return model; } /// /// Prepare proxy connection warning model /// /// List of system warning models /// A task that represents the asynchronous operation protected virtual async Task PrepareProxyConnectionWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //whether proxy is enabled if (!_proxySettings.Enabled) return; try { await _nopHttpClient.PingAsync(); //connection is OK models.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.ProxyConnection.OK") }); } catch { //connection failed models.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = await _localizationService.GetResourceAsync("Admin.System.Warnings.ProxyConnection.Failed") }); } } /// /// Prepare plugins warning model /// /// List of system warning models /// A task that represents the asynchronous operation public virtual async Task PreparePluginsWarningModelAsync(IList models) { ArgumentNullException.ThrowIfNull(models); //incompatible plugins await PrepareIncompatibleWarningModelAsync(models); //collision of loaded assembly await PreparePluginsCollisionsWarningModelAsync(models); //override the same interface await PreparePluginsOverrideSameInterfaceWarningModelAsync(models); //not active plugins await PreparePluginsEnabledWarningModelAsync(models); //not install plugins await PreparePluginsInstalledWarningModelAsync(models); } /// /// Prepare system warning models /// /// /// A task that represents the asynchronous operation /// The task result contains the list of system warning models /// public virtual async Task> PrepareSystemWarningModelsAsync() { var models = new List(); //store URL await PrepareStoreUrlWarningModelAsync(models); //primary exchange rate currency await PrepareExchangeRateCurrencyWarningModelAsync(models); //primary store currency await PreparePrimaryStoreCurrencyWarningModelAsync(models); //base measure weight await PrepareBaseWeightWarningModelAsync(models); //base dimension weight await PrepareBaseDimensionWarningModelAsync(models); //payment methods await PreparePaymentMethodsWarningModelAsync(models); //performance settings await PreparePerformanceSettingsWarningModelAsync(models); //validate write permissions (the same procedure like during installation) await PrepareFilePermissionsWarningModelAsync(models); //plugins await PreparePluginsWarningModelAsync(models); //proxy connection await PrepareProxyConnectionWarningModelAsync(models); //publish event var warningEvent = new SystemWarningCreatedEvent(); await _eventPublisher.PublishAsync(warningEvent); //add another warnings (for example from plugins) models.AddRange(warningEvent.SystemWarnings); return models; } /// /// Prepare maintenance model /// /// Maintenance model /// /// A task that represents the asynchronous operation /// The task result contains the maintenance model /// public virtual Task PrepareMaintenanceModelAsync(MaintenanceModel model) { ArgumentNullException.ThrowIfNull(model); model.DeleteGuests.EndDate = DateTime.UtcNow.AddDays(-7); model.DeleteGuests.OnlyWithoutShoppingCart = true; model.DeleteAbandonedCarts.OlderThan = DateTime.UtcNow.AddDays(-182); model.DeleteAlreadySentQueuedEmails.EndDate = DateTime.UtcNow.AddDays(-7); model.BackupSupported = _dataProvider.BackupSupported; //prepare nested search model PrepareBackupFileSearchModel(model.BackupFileSearchModel); return Task.FromResult(model); } /// /// Prepare paged backup file list model /// /// Backup file search model /// /// A task that represents the asynchronous operation /// The task result contains the backup file list model /// public virtual Task PrepareBackupFileListModelAsync(BackupFileSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get backup files var backupFiles = _maintenanceService.GetAllBackupFiles().ToPagedList(searchModel); //prepare list model var model = new BackupFileListModel().PrepareToGrid(searchModel, backupFiles, () => { return backupFiles.Select(file => new BackupFileModel { Name = _fileProvider.GetFileName(file), //fill in additional values (not existing in the entity) Length = $"{_fileProvider.FileLength(file) / 1024f / 1024f:F2} Mb", Link = $"{_webHelper.GetStoreLocation()}db_backups/{_fileProvider.GetFileName(file)}" }); }); return Task.FromResult(model); } /// /// Prepare URL record search model /// /// URL record search model /// /// A task that represents the asynchronous operation /// The task result contains the uRL record search model /// public virtual async Task PrepareUrlRecordSearchModelAsync(UrlRecordSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare available languages //we insert 0 as 'Standard' language. //let's insert -1 for 'All' language selection. await _baseAdminModelFactory.PrepareLanguagesAsync(searchModel.AvailableLanguages, defaultItemText: await _localizationService.GetResourceAsync("Admin.System.SeNames.List.Language.Standard")); searchModel.AvailableLanguages.Insert(0, new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = "-1" }); searchModel.LanguageId = -1; //prepare "is active" filter (0 - all; 1 - active only; 2 - inactive only) searchModel.AvailableActiveOptions.Add(new SelectListItem { Value = "0", Text = await _localizationService.GetResourceAsync("Admin.System.SeNames.List.IsActive.All") }); searchModel.AvailableActiveOptions.Add(new SelectListItem { Value = "1", Text = await _localizationService.GetResourceAsync("Admin.System.SeNames.List.IsActive.ActiveOnly") }); searchModel.AvailableActiveOptions.Add(new SelectListItem { Value = "2", Text = await _localizationService.GetResourceAsync("Admin.System.SeNames.List.IsActive.InactiveOnly") }); //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } /// /// Prepare paged URL record list model /// /// URL record search model /// /// A task that represents the asynchronous operation /// The task result contains the uRL record list model /// public virtual async Task PrepareUrlRecordListModelAsync(UrlRecordSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); var isActive = searchModel.IsActiveId == 0 ? null : (bool?)(searchModel.IsActiveId == 1); var languageId = searchModel.LanguageId < 0 ? null : (int?)(searchModel.LanguageId); //get URL records var urlRecords = await _urlRecordService.GetAllUrlRecordsAsync(slug: searchModel.SeName, languageId: languageId, isActive: isActive, pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize); //get URL helper var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext); //prepare list model var model = await new UrlRecordListModel().PrepareToGridAsync(searchModel, urlRecords, () => { return urlRecords.SelectAwait(async urlRecord => { //fill in model values from the entity var urlRecordModel = urlRecord.ToModel(); //fill in additional values (not existing in the entity) urlRecordModel.Name = urlRecord.Slug; urlRecordModel.Language = urlRecord.LanguageId == 0 ? await _localizationService.GetResourceAsync("Admin.System.SeNames.Language.Standard") : (await _languageService.GetLanguageByIdAsync(urlRecord.LanguageId))?.Name ?? "Unknown"; //details URL var detailsUrl = string.Empty; var entityName = urlRecord.EntityName?.ToLowerInvariant() ?? string.Empty; switch (entityName) { case "blogpost": detailsUrl = urlHelper.Action("BlogPostEdit", "Blog", new { id = urlRecord.EntityId }); break; case "category": detailsUrl = urlHelper.Action("Edit", "Category", new { id = urlRecord.EntityId }); break; case "manufacturer": detailsUrl = urlHelper.Action("Edit", "Manufacturer", new { id = urlRecord.EntityId }); break; case "product": detailsUrl = urlHelper.Action("Edit", "Product", new { id = urlRecord.EntityId }); break; case "newsitem": detailsUrl = urlHelper.Action("NewsItemEdit", "News", new { id = urlRecord.EntityId }); break; case "topic": detailsUrl = urlHelper.Action("Edit", "Topic", new { id = urlRecord.EntityId }); break; case "vendor": detailsUrl = urlHelper.Action("Edit", "Vendor", new { id = urlRecord.EntityId }); break; } urlRecordModel.DetailsUrl = detailsUrl; return urlRecordModel; }); }); return model; } /// /// Prepare language selector model /// /// /// A task that represents the asynchronous operation /// The task result contains the language selector model /// public virtual async Task PrepareLanguageSelectorModelAsync() { var store = await _storeContext.GetCurrentStoreAsync(); var model = new LanguageSelectorModel { CurrentLanguage = (await _workContext.GetWorkingLanguageAsync()).ToModel(), AvailableLanguages = (await _languageService .GetAllLanguagesAsync(storeId: store.Id)) .Select(language => language.ToModel()).ToList() }; return model; } /// /// Prepare popular search term search model /// /// Popular search term search model /// /// A task that represents the asynchronous operation /// The task result contains the popular search term search model /// public virtual Task PreparePopularSearchTermSearchModelAsync(PopularSearchTermSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(5); return Task.FromResult(searchModel); } /// /// Prepare paged popular search term list model /// /// Popular search term search model /// /// A task that represents the asynchronous operation /// The task result contains the popular search term list model /// public virtual async Task PreparePopularSearchTermListModelAsync(PopularSearchTermSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get popular search terms var searchTermRecordLines = await _searchTermService.GetStatsAsync(pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize); //prepare list model var model = new PopularSearchTermListModel().PrepareToGrid(searchModel, searchTermRecordLines, () => { return searchTermRecordLines.Select(searchTerm => new PopularSearchTermModel { Keyword = searchTerm.Keyword, Count = searchTerm.Count }); }); return model; } /// /// Prepare common statistics model /// /// /// A task that represents the asynchronous operation /// The task result contains the common statistics model /// public virtual async Task PrepareCommonStatisticsModelAsync() { var model = new CommonStatisticsModel { NumberOfOrders = (await _orderService.SearchOrdersAsync(pageIndex: 0, pageSize: 1, getOnlyTotalCount: true)).TotalCount }; var customerRoleIds = new[] { (await _customerService.GetCustomerRoleBySystemNameAsync(NopCustomerDefaults.RegisteredRoleName)).Id }; model.NumberOfCustomers = (await _customerService.GetAllCustomersAsync(customerRoleIds: customerRoleIds, pageIndex: 0, pageSize: 1, getOnlyTotalCount: true)).TotalCount; var returnRequestStatus = ReturnRequestStatus.Pending; model.NumberOfPendingReturnRequests = (await _returnRequestService.SearchReturnRequestsAsync(rs: returnRequestStatus, pageIndex: 0, pageSize: 1, getOnlyTotalCount: true)).TotalCount; model.NumberOfLowStockProducts = (await _productService.GetLowStockProductsAsync(getOnlyTotalCount: true)).TotalCount + (await _productService.GetLowStockProductCombinationsAsync(getOnlyTotalCount: true)).TotalCount; return model; } /// /// Prepare multistore preview models /// /// Model type /// Entity model /// /// A task that represents the asynchronous operation /// The task result contains the list of multistore preview models /// public virtual async Task> PrepareMultistorePreviewModelsAsync(TModel model) where TModel : BaseNopEntityModel { switch (model) { case BlogPostModel blogPostModel: var blogPost = await _blogService.GetBlogPostByIdAsync(blogPostModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(blogPost); case CategoryModel categoryModel: var category = await _categoryService.GetCategoryByIdAsync(categoryModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(category); case ManufacturerModel manufacturerModel: var manufacturerEntity = await _manufacturerService.GetManufacturerByIdAsync(manufacturerModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(manufacturerEntity); case NewsItemModel newsItemModel: var newsItem = await _newsService.GetNewsByIdAsync(newsItemModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(newsItem); case ProductModel productModel: var product = await _productService.GetProductByIdAsync(productModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(product); case TopicModel topicModel: var topic = await _topicService.GetTopicByIdAsync(topicModel.Id); return await PrepareMultistorePreviewModelsForEntityAsync(topic); default: throw new NotImplementedException("Unknown entity type"); } } #endregion }