diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7920af5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.suo +*.user +_ReSharper.* +bin +obj +packages \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/Admin/ApiAdminController.cs b/Areas/Admin/Controllers/ApiAdminController.cs similarity index 54% rename from Nop.Plugin.Api/Controllers/Admin/ApiAdminController.cs rename to Areas/Admin/Controllers/ApiAdminController.cs index d5e3ab9..f3265ac 100644 --- a/Nop.Plugin.Api/Controllers/Admin/ApiAdminController.cs +++ b/Areas/Admin/Controllers/ApiAdminController.cs @@ -1,95 +1,89 @@ -namespace Nop.Plugin.Api.Controllers.Admin -{ - using Microsoft.AspNetCore.Mvc; - using Core; - using Constants; - using Domain; - using MappingExtensions; - using Models; - using Nop.Services.Configuration; - using Nop.Services.Localization; - using Nop.Services.Logging; - using Nop.Services.Stores; - using Web.Framework; - using Nop.Web.Framework.Controllers; - using Web.Framework.Mvc.Filters; - - [AuthorizeAdmin] - [Area(AreaNames.Admin)] - public class ApiAdminController : BasePluginController - { - private readonly IStoreService _storeService; - private readonly IStoreContext _storeContext; - private readonly IWorkContext _workContext; - private readonly ISettingService _settingService; - private readonly ICustomerActivityService _customerActivityService; - private readonly ILocalizationService _localizationService; - - public ApiAdminController( - IStoreService storeService, - IStoreContext storeContext, - IWorkContext workContext, - ISettingService settingService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService) - { - _storeService = storeService; - _storeContext = storeContext; - _workContext = workContext; - _settingService = settingService; - _customerActivityService = customerActivityService; - _localizationService = localizationService; - } - - [HttpGet] - public ActionResult Settings() - { - - var storeScope = _storeContext.ActiveStoreScopeConfiguration; - - var apiSettings = _settingService.LoadSetting(storeScope); - - var model = apiSettings.ToModel(); - - // Store Settings - model.ActiveStoreScopeConfiguration = storeScope; - - if (model.EnableApi_OverrideForStore || storeScope == 0) - _settingService.SaveSetting(apiSettings, x => x.EnableApi, storeScope, false); - if (model.AllowRequestsFromSwagger_OverrideForStore || storeScope == 0) - _settingService.SaveSetting(apiSettings, x => x.AllowRequestsFromSwagger, storeScope, false); - - //now clear settings cache - _settingService.ClearCache(); - - return View(ViewNames.AdminApiSettings, model); - } - - [HttpPost] - public ActionResult Settings(ConfigurationModel configurationModel) - { - //load settings for a chosen store scope - var storeScope = _storeContext.ActiveStoreScopeConfiguration; - - var settings = configurationModel.ToEntity(); - - /* We do not clear cache after each setting update. - * This behavior can increase performance because cached settings will not be cleared - * and loaded from database after each update */ - - if (configurationModel.EnableApi_OverrideForStore || storeScope == 0) - _settingService.SaveSetting(settings, x => x.EnableApi, storeScope, false); - if (configurationModel.AllowRequestsFromSwagger_OverrideForStore || storeScope == 0) - _settingService.SaveSetting(settings, x => x.AllowRequestsFromSwagger, storeScope, false); - - //now clear settings cache - _settingService.ClearCache(); - - _customerActivityService.InsertActivity("EditApiSettings", "Edit Api Settings"); - - SuccessNotification(_localizationService.GetResource("Admin.Plugins.Saved")); - - return View(ViewNames.AdminApiSettings, configurationModel); - } - } -} \ No newline at end of file +using Microsoft.AspNetCore.Mvc; +using Nop.Core; +using Nop.Plugin.Api.Areas.Admin.Models; +using Nop.Plugin.Api.Domain; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Services.Configuration; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Messages; +using Nop.Web.Framework; +using Nop.Web.Framework.Controllers; +using Nop.Web.Framework.Mvc.Filters; + +namespace Nop.Plugin.Api.Areas.Admin.Controllers +{ + [AuthorizeAdmin] + [Area(AreaNames.Admin)] + public class ApiAdminController : BasePluginController + { + private readonly ICustomerActivityService _customerActivityService; + private readonly ILocalizationService _localizationService; + private readonly INotificationService _notificationService; + private readonly ISettingService _settingService; + private readonly IStoreContext _storeContext; + + public ApiAdminController( + IStoreContext storeContext, + ISettingService settingService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + INotificationService notificationService) + { + _storeContext = storeContext; + _settingService = settingService; + _customerActivityService = customerActivityService; + _localizationService = localizationService; + _notificationService = notificationService; + } + + [HttpGet] + public IActionResult Settings() + { + var storeScope = _storeContext.ActiveStoreScopeConfiguration; + var apiSettings = _settingService.LoadSetting(storeScope); + var model = apiSettings.ToModel(); + + // Store Settings + model.ActiveStoreScopeConfiguration = storeScope; + + if (model.EnableApi_OverrideForStore || storeScope == 0) + { + _settingService.SaveSetting(apiSettings, x => x.EnableApi, storeScope, false); + } + + //now clear settings cache + _settingService.ClearCache(); + + return View($"~/Plugins/Nop.Plugin.Api/Areas/Admin/Views/ApiAdmin/Settings.cshtml", model); + } + + [HttpPost] + public IActionResult Settings(ConfigurationModel model) + { + //load settings for a chosen store scope + var storeScope = _storeContext.ActiveStoreScopeConfiguration; + + var settings = model.ToEntity(); + + /* We do not clear cache after each setting update. + * This behavior can increase performance because cached settings will not be cleared + * and loaded from database after each update */ + + if (model.EnableApi_OverrideForStore || storeScope == 0) + { + _settingService.SaveSetting(settings, x => x.EnableApi, storeScope, false); + } + + //now clear settings cache + _settingService.ClearCache(); + + _customerActivityService.InsertActivity("EditApiSettings", "Edit Api Settings"); + + _notificationService.SuccessNotification(_localizationService.GetResource("Admin.Plugins.Saved")); + + return View($"~/Plugins/Nop.Plugin.Api/Areas/Admin/Views/ApiAdmin/Settings.cshtml", model); + } + } +} + \ No newline at end of file diff --git a/Nop.Plugin.Api/Models/ConfigurationModel.cs b/Areas/Admin/Models/ConfigurationModel.cs similarity index 88% rename from Nop.Plugin.Api/Models/ConfigurationModel.cs rename to Areas/Admin/Models/ConfigurationModel.cs index b71c6ae..28f7968 100644 --- a/Nop.Plugin.Api/Models/ConfigurationModel.cs +++ b/Areas/Admin/Models/ConfigurationModel.cs @@ -1,7 +1,7 @@ -namespace Nop.Plugin.Api.Models -{ - using Nop.Web.Framework.Mvc.ModelBinding; +using Nop.Web.Framework.Mvc.ModelBinding; +namespace Nop.Plugin.Api.Areas.Admin.Models +{ public class ConfigurationModel { [NopResourceDisplayName("Plugins.Api.Admin.EnableApi")] diff --git a/Nop.Plugin.Api/Views/Settings.cshtml b/Areas/Admin/Views/ApiAdmin/Settings.cshtml similarity index 51% rename from Nop.Plugin.Api/Views/Settings.cshtml rename to Areas/Admin/Views/ApiAdmin/Settings.cshtml index 27fbca1..1a4a607 100644 --- a/Nop.Plugin.Api/Views/Settings.cshtml +++ b/Areas/Admin/Views/ApiAdmin/Settings.cshtml @@ -1,13 +1,14 @@ -@model ConfigurationModel +@using Nop.Plugin.Api.Infrastructure +@model Nop.Plugin.Api.Areas.Admin.Models.ConfigurationModel -@{ - Layout = ViewNames.AdminLayout; +@{ + Layout = Constants.ViewNames.AdminLayout; //page title ViewBag.Title = T("Plugins.Api.Admin.Page.Settings.Title").Text; //active menu item (system name) - Html.SetActiveMenuItemSystemName("Api-Settings-Menu"); + Html.SetActiveMenuItemSystemName("Api-Settings-Menu"); }
@@ -28,7 +29,6 @@
@await Component.InvokeAsync("StoreScopeConfiguration") - @await Component.InvokeAsync("SettingMode") @Html.ValidationSummary(false)
@@ -44,26 +44,6 @@
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
diff --git a/Nop.Plugin.Api/Views/_ViewImports.cshtml b/Areas/Admin/Views/_ViewImports.cshtml similarity index 66% rename from Nop.Plugin.Api/Views/_ViewImports.cshtml rename to Areas/Admin/Views/_ViewImports.cshtml index 3a80be5..48841e6 100644 --- a/Nop.Plugin.Api/Views/_ViewImports.cshtml +++ b/Areas/Admin/Views/_ViewImports.cshtml @@ -2,7 +2,5 @@ @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, Nop.Web.Framework -@using Nop.Plugin.Api.Constants @using Nop.Web.Framework.UI -@using Nop.Plugin.Api.Models; -@using IdentityServer4.Models; \ No newline at end of file +@using Nop.Plugin.Api.Models diff --git a/Attributes/ApiAuthorize.cs b/Attributes/ApiAuthorize.cs new file mode 100644 index 0000000..df0ee87 --- /dev/null +++ b/Attributes/ApiAuthorize.cs @@ -0,0 +1,42 @@ +//namespace Nop.Plugin.Api.Attributes +//{ +// using Microsoft.AspNetCore.Authorization; +// using Nop.Core.Infrastructure; +// using Nop.Services.Plugins; + +// // We need the ApiAuthorize attribute because when the api plugin assembly is loaded in memory by PluginManager +// // all of its attributes are being initialized by the .NetFramework. +// // The authorize attribute of the api plugin is marked with the Bearer authentication scheme, but the scheme is registered in the ApiStartup class, +// // which is called on plugin install. +// // If the plugin is not installed the authorize attribute will still be initialized when the assembly is loaded in memory, but the scheme won't be registered, +// // which will cause an exception. +// // That is why we need to make sure that the plugin is installed before setting the scheme. +// public class ApiAuthorize : AuthorizeAttribute +// { + +// public new string Policy +// { +// get => base.AuthenticationSchemes; +// set => base.AuthenticationSchemes = GetAuthenticationSchemeName(value); +// } + +// public new string AuthenticationSchemes +// { +// get => base.AuthenticationSchemes; +// set => base.AuthenticationSchemes = GetAuthenticationSchemeName(value); +// } + +// private string GetAuthenticationSchemeName(string value) +// { +// var pluginService = EngineContext.Current.Resolve(); +// var pluginInstalled = pluginService.FindPluginByTypeInAssembly(typeof(ApiStartup))?.PluginDescriptor.Installed ?? false; + +// if (pluginInstalled) +// { +// return value; +// } + +// return default(string); +// } +// } +//} \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/BaseAttributeInvoker.cs b/Attributes/BaseAttributeInvoker.cs similarity index 100% rename from Nop.Plugin.Api/Attributes/BaseAttributeInvoker.cs rename to Attributes/BaseAttributeInvoker.cs diff --git a/Nop.Plugin.Api/Attributes/DoNotMap.cs b/Attributes/DoNotMap.cs similarity index 100% rename from Nop.Plugin.Api/Attributes/DoNotMap.cs rename to Attributes/DoNotMap.cs diff --git a/Nop.Plugin.Api/Attributes/GetRequestsErrorInterceptorActionFilter.cs b/Attributes/GetRequestsErrorInterceptorActionFilter.cs similarity index 96% rename from Nop.Plugin.Api/Attributes/GetRequestsErrorInterceptorActionFilter.cs rename to Attributes/GetRequestsErrorInterceptorActionFilter.cs index 161a089..a96bd1e 100644 --- a/Nop.Plugin.Api/Attributes/GetRequestsErrorInterceptorActionFilter.cs +++ b/Attributes/GetRequestsErrorInterceptorActionFilter.cs @@ -1,77 +1,77 @@ -using System.Collections.Generic; -using System.IO; -using System.Net; -using Microsoft.AspNetCore.Mvc.Filters; -using Newtonsoft.Json; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.JSON.Serializers; -using Nop.Plugin.Api.Models; - -namespace Nop.Plugin.Api.Attributes -{ - public class GetRequestsErrorInterceptorActionFilter : ActionFilterAttribute - { - private readonly IJsonFieldsSerializer _jsonFieldsSerializer; - - public GetRequestsErrorInterceptorActionFilter() - { - _jsonFieldsSerializer = EngineContext.Current.Resolve(); - } - - public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) - { - if (actionExecutedContext.Exception != null && !actionExecutedContext.ExceptionHandled) - { - var error = new KeyValuePair>("internal_server_error", - new List {"please, contact the store owner"}); - - actionExecutedContext.Exception = null; - actionExecutedContext.ExceptionHandled = true; - SetError(actionExecutedContext, error); - } - else if (actionExecutedContext.HttpContext.Response != null && - (HttpStatusCode) actionExecutedContext.HttpContext.Response.StatusCode != HttpStatusCode.OK) - { - string responseBody; - - using (var streamReader = new StreamReader(actionExecutedContext.HttpContext.Response.Body)) - { - responseBody = streamReader.ReadToEnd(); - } - - // reset reader possition. - actionExecutedContext.HttpContext.Response.Body.Position = 0; - - var defaultWebApiErrorsModel = JsonConvert.DeserializeObject(responseBody); - - // If both are null this means that it is not the default web api error format, - // which means that it the error is formatted by our standard and we don't need to do anything. - if (!string.IsNullOrEmpty(defaultWebApiErrorsModel.Message) && - !string.IsNullOrEmpty(defaultWebApiErrorsModel.MessageDetail)) - { - var error = new KeyValuePair>("lookup_error", new List {"not found"}); - - SetError(actionExecutedContext, error); - } - } - - base.OnActionExecuted(actionExecutedContext); - } - - private void SetError(ActionExecutedContext actionExecutedContext, KeyValuePair> error) - { - var bindingError = new Dictionary> {{error.Key, error.Value}}; - - var errorsRootObject = new ErrorsRootObject - { - Errors = bindingError - }; - - var errorJson = _jsonFieldsSerializer.Serialize(errorsRootObject, null); - - actionExecutedContext.Result = new ErrorActionResult(errorJson, HttpStatusCode.BadRequest); - } - } +using System.Collections.Generic; +using System.IO; +using System.Net; +using Microsoft.AspNetCore.Mvc.Filters; +using Newtonsoft.Json; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.Models; + +namespace Nop.Plugin.Api.Attributes +{ + public class GetRequestsErrorInterceptorActionFilter : ActionFilterAttribute + { + private readonly IJsonFieldsSerializer _jsonFieldsSerializer; + + public GetRequestsErrorInterceptorActionFilter() + { + _jsonFieldsSerializer = EngineContext.Current.Resolve(); + } + + public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) + { + if (actionExecutedContext.Exception != null && !actionExecutedContext.ExceptionHandled) + { + var error = new KeyValuePair>("internal_server_error", + new List {"please, contact the store owner"}); + + actionExecutedContext.Exception = null; + actionExecutedContext.ExceptionHandled = true; + SetError(actionExecutedContext, error); + } + else if (actionExecutedContext.HttpContext.Response != null && + (HttpStatusCode) actionExecutedContext.HttpContext.Response.StatusCode != HttpStatusCode.OK) + { + string responseBody; + + using (var streamReader = new StreamReader(actionExecutedContext.HttpContext.Response.Body)) + { + responseBody = streamReader.ReadToEnd(); + } + + // reset reader possition. + actionExecutedContext.HttpContext.Response.Body.Position = 0; + + var defaultWebApiErrorsModel = JsonConvert.DeserializeObject(responseBody); + + // If both are null this means that it is not the default web api error format, + // which means that it the error is formatted by our standard and we don't need to do anything. + if (!string.IsNullOrEmpty(defaultWebApiErrorsModel.Message) && + !string.IsNullOrEmpty(defaultWebApiErrorsModel.MessageDetail)) + { + var error = new KeyValuePair>("lookup_error", new List {"not found"}); + + SetError(actionExecutedContext, error); + } + } + + base.OnActionExecuted(actionExecutedContext); + } + + private void SetError(ActionExecutedContext actionExecutedContext, KeyValuePair> error) + { + var bindingError = new Dictionary> {{error.Key, error.Value}}; + + var errorsRootObject = new ErrorsRootObject + { + Errors = bindingError + }; + + var errorJson = _jsonFieldsSerializer.Serialize(errorsRootObject, null); + + actionExecutedContext.Result = new ErrorActionResult(errorJson, HttpStatusCode.BadRequest); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/ImageAttribute.cs b/Attributes/ImageAttribute.cs similarity index 96% rename from Nop.Plugin.Api/Attributes/ImageAttribute.cs rename to Attributes/ImageAttribute.cs index 764c7a2..d943deb 100644 --- a/Nop.Plugin.Api/Attributes/ImageAttribute.cs +++ b/Attributes/ImageAttribute.cs @@ -1,170 +1,171 @@ -using System.Collections.Generic; -using System.Net; -using Nop.Plugin.Api.DTOs.Images; -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using Nop.Core.Infrastructure; -using Nop.Services.Media; - -namespace Nop.Plugin.Api.Attributes -{ - public class ImageValidationAttribute : BaseValidationAttribute - { - private Dictionary _errors; - private readonly IPictureService _pictureService; - - public ImageValidationAttribute() - { - _errors = new Dictionary(); - _pictureService = EngineContext.Current.Resolve(); - } - - public override void Validate(object instance) - { - var imageDto = instance as ImageDto; - - var imageSrcSet = imageDto != null && !string.IsNullOrEmpty(imageDto.Src); - var imageAttachmentSet = imageDto != null && !string.IsNullOrEmpty(imageDto.Attachment); - - if (imageSrcSet || imageAttachmentSet) - { - byte[] imageBytes = null; - var mimeType = string.Empty; - - // Validation of the image object - - // We can't have both set. - CheckIfBothImageSourceTypesAreSet(imageSrcSet, imageAttachmentSet); - - // Here we ensure that the validation to this point has passed - // and try to download the image or convert base64 format to byte array - // depending on which format is passed. In both cases we should get a byte array and mime type. - if (_errors.Count == 0) - { - if (imageSrcSet) - { - DownloadFromSrc(imageDto.Src, ref imageBytes, ref mimeType); - } - else if (imageAttachmentSet) - { - ValidateAttachmentFormat(imageDto.Attachment); - - if (_errors.Count == 0) - { - ConvertAttachmentToByteArray(imageDto.Attachment, ref imageBytes, - ref mimeType); - } - } - } - - // We need to check because some of the validation above may have render the models state invalid. - if (_errors.Count == 0) - { - // Here we handle the check if the file passed is actual image and if the image is valid according to the - // restrictions set in the administration. - ValidatePictureBiteArray(imageBytes, mimeType); - } - - imageDto.Binary = imageBytes; - imageDto.MimeType = mimeType; - } - } - - public override Dictionary GetErrors() - { - return _errors; - } - - private void CheckIfBothImageSourceTypesAreSet(bool imageSrcSet, bool imageAttachmentSet) - { - if (imageSrcSet && - imageAttachmentSet) - { - var key = string.Format("{0} type", "image"); - _errors.Add(key, "Image src and Attachment are both set"); - } - } - - private void DownloadFromSrc(string imageSrc, ref byte[] imageBytes, ref string mimeType) - { - var key = string.Format("{0} type", "image"); - // TODO: discuss if we need our own web client so we can set a custom tmeout - this one's timeout is 100 sec. - var client = new WebClient(); - - try - { - imageBytes = client.DownloadData(imageSrc); - // This needs to be after the downloadData is called from client, otherwise there won't be any response headers. - mimeType = client.ResponseHeaders["content-type"]; - - if (imageBytes == null) - { - _errors.Add(key, "src is invalid"); - } - } - catch (Exception ex) - { - var message = string.Format("{0} - {1}", "src is invalid", ex.Message); - - _errors.Add(key, message); - } - } - - private void ValidateAttachmentFormat(string attachment) - { - var validBase64Pattern = - new Regex("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"); - var isMatch = validBase64Pattern.IsMatch(attachment); - if (!isMatch) - { - var key = string.Format("{0} type", "image"); - _errors.Add(key, "attachment format is invalid"); - } - } - - private void ConvertAttachmentToByteArray(string attachment, ref byte[] imageBytes, ref string mimeType) - { - imageBytes = Convert.FromBase64String(attachment); - mimeType = GetMimeTypeFromByteArray(imageBytes); - } - - private static string GetMimeTypeFromByteArray(byte[] imageBytes) - { - var stream = new MemoryStream(imageBytes, 0, imageBytes.Length); - var image = Image.FromStream(stream, true); - var format = image.RawFormat; - var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid); - return codec.MimeType; - } - - private void ValidatePictureBiteArray(byte[] imageBytes, string mimeType) - { - if (imageBytes != null) - { - try - { - imageBytes = _pictureService.ValidatePicture(imageBytes, mimeType); - } - catch (Exception ex) - { - var key = string.Format("{0} invalid", "image"); - var message = string.Format("{0} - {1}", "source is invalid", ex.Message); - - _errors.Add(key, message); - } - } - - if (imageBytes == null) - { - var key = string.Format("{0} invalid", "image"); - var message = "You have provided an invalid image source/attachment"; - - _errors.Add(key, message); - } - } - } +using System.Collections.Generic; +using System.Net; +using Nop.Plugin.Api.DTO.Images; +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Nop.Core.Infrastructure; +using Nop.Services.Media; +using FluentValidation; + +namespace Nop.Plugin.Api.Attributes +{ + public class ImageValidationAttribute : BaseValidationAttribute + { + private Dictionary _errors; + private readonly IPictureService _pictureService; + + public ImageValidationAttribute() + { + _errors = new Dictionary(); + _pictureService = EngineContext.Current.Resolve(); + } + + public override void Validate(object instance) + { + var imageDto = instance as ImageDto; + + var imageSrcSet = imageDto != null && !string.IsNullOrEmpty(imageDto.Src); + var imageAttachmentSet = imageDto != null && !string.IsNullOrEmpty(imageDto.Attachment); + + if (imageSrcSet || imageAttachmentSet) + { + byte[] imageBytes = null; + var mimeType = string.Empty; + + // Validation of the image object + + // We can't have both set. + CheckIfBothImageSourceTypesAreSet(imageSrcSet, imageAttachmentSet); + + // Here we ensure that the validation to this point has passed + // and try to download the image or convert base64 format to byte array + // depending on which format is passed. In both cases we should get a byte array and mime type. + if (_errors.Count == 0) + { + if (imageSrcSet) + { + DownloadFromSrc(imageDto.Src, ref imageBytes, ref mimeType); + } + else if (imageAttachmentSet) + { + ValidateAttachmentFormat(imageDto.Attachment); + + if (_errors.Count == 0) + { + ConvertAttachmentToByteArray(imageDto.Attachment, ref imageBytes, + ref mimeType); + } + } + } + + // We need to check because some of the validation above may have render the models state invalid. + if (_errors.Count == 0) + { + // Here we handle the check if the file passed is actual image and if the image is valid according to the + // restrictions set in the administration. + ValidatePictureBiteArray(imageBytes, mimeType); + } + + imageDto.Binary = imageBytes; + imageDto.MimeType = mimeType; + } + } + + public override Dictionary GetErrors() + { + return _errors; + } + + private void CheckIfBothImageSourceTypesAreSet(bool imageSrcSet, bool imageAttachmentSet) + { + if (imageSrcSet && + imageAttachmentSet) + { + var key = string.Format("{0} type", "image"); + _errors.Add(key, "Image src and Attachment are both set"); + } + } + + private void DownloadFromSrc(string imageSrc, ref byte[] imageBytes, ref string mimeType) + { + var key = string.Format("{0} type", "image"); + // TODO: discuss if we need our own web client so we can set a custom tmeout - this one's timeout is 100 sec. + var client = new WebClient(); + + try + { + imageBytes = client.DownloadData(imageSrc); + // This needs to be after the downloadData is called from client, otherwise there won't be any response headers. + mimeType = client.ResponseHeaders["content-type"]; + + if (imageBytes == null) + { + _errors.Add(key, "src is invalid"); + } + } + catch (Exception ex) + { + var message = string.Format("{0} - {1}", "src is invalid", ex.Message); + + _errors.Add(key, message); + } + } + + private void ValidateAttachmentFormat(string attachment) + { + var validBase64Pattern = + new Regex("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"); + var isMatch = validBase64Pattern.IsMatch(attachment); + if (!isMatch) + { + var key = string.Format("{0} type", "image"); + _errors.Add(key, "attachment format is invalid"); + } + } + + private void ConvertAttachmentToByteArray(string attachment, ref byte[] imageBytes, ref string mimeType) + { + imageBytes = Convert.FromBase64String(attachment); + mimeType = GetMimeTypeFromByteArray(imageBytes); + } + + private static string GetMimeTypeFromByteArray(byte[] imageBytes) + { + var stream = new MemoryStream(imageBytes, 0, imageBytes.Length); + var image = Image.FromStream(stream, true); + var format = image.RawFormat; + var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid); + return codec.MimeType; + } + + private void ValidatePictureBiteArray(byte[] imageBytes, string mimeType) + { + if (imageBytes != null) + { + try + { + imageBytes = _pictureService.ValidatePicture(imageBytes, mimeType); + } + catch (Exception ex) + { + var key = string.Format("{0} invalid", "image"); + var message = string.Format("{0} - {1}", "source is invalid", ex.Message); + + _errors.Add(key, message); + } + } + + if (imageBytes == null) + { + var key = string.Format("{0} invalid", "image"); + var message = "You have provided an invalid image source/attachment"; + + _errors.Add(key, message); + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/ImageCollectionAttribute.cs b/Attributes/ImageCollectionAttribute.cs similarity index 94% rename from Nop.Plugin.Api/Attributes/ImageCollectionAttribute.cs rename to Attributes/ImageCollectionAttribute.cs index eefe1d7..c99dac7 100644 --- a/Nop.Plugin.Api/Attributes/ImageCollectionAttribute.cs +++ b/Attributes/ImageCollectionAttribute.cs @@ -1,40 +1,40 @@ -using System.Collections.Generic; -using Nop.Plugin.Api.DTOs.Images; - -namespace Nop.Plugin.Api.Attributes -{ - public class ImageCollectionValidationAttribute : BaseValidationAttribute - { - private Dictionary _errors = new Dictionary(); - - public override void Validate(object instance) - { - // Images are not required so they could be null - // and there is nothing to validate in this case - if (instance == null) - return; - - var imagesCollection = instance as ICollection; - - foreach (var image in imagesCollection) - { - var imageValidationAttribute = new ImageValidationAttribute(); - - imageValidationAttribute.Validate(image); - - var errorsForImage = imageValidationAttribute.GetErrors(); - - if (errorsForImage.Count > 0) - { - _errors = errorsForImage; - break; - } - } - } - - public override Dictionary GetErrors() - { - return _errors; - } - } +using System.Collections.Generic; +using Nop.Plugin.Api.DTO.Images; + +namespace Nop.Plugin.Api.Attributes +{ + public class ImageCollectionValidationAttribute : BaseValidationAttribute + { + private Dictionary _errors = new Dictionary(); + + public override void Validate(object instance) + { + // Images are not required so they could be null + // and there is nothing to validate in this case + if (instance == null) + return; + + var imagesCollection = instance as ICollection; + + foreach (var image in imagesCollection) + { + var imageValidationAttribute = new ImageValidationAttribute(); + + imageValidationAttribute.Validate(image); + + var errorsForImage = imageValidationAttribute.GetErrors(); + + if (errorsForImage.Count > 0) + { + _errors = errorsForImage; + break; + } + } + } + + public override Dictionary GetErrors() + { + return _errors; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/ProductTypeValidationAttribute.cs b/Attributes/ProductTypeValidationAttribute.cs similarity index 96% rename from Nop.Plugin.Api/Attributes/ProductTypeValidationAttribute.cs rename to Attributes/ProductTypeValidationAttribute.cs index 4cc2b67..de7253f 100644 --- a/Nop.Plugin.Api/Attributes/ProductTypeValidationAttribute.cs +++ b/Attributes/ProductTypeValidationAttribute.cs @@ -1,31 +1,31 @@ -using System; -using System.Collections.Generic; -using Nop.Core.Domain.Catalog; - -namespace Nop.Plugin.Api.Attributes -{ - public class ProductTypeValidationAttribute : BaseValidationAttribute - { - private readonly Dictionary _errors = new Dictionary(); - - public override void Validate(object instance) - { - // Product Type is not required so it could be null - // and there is nothing to validate in this case - if (instance == null) - return; - - var isDefined = Enum.IsDefined(typeof(ProductType), instance); - - if (!isDefined) - { - _errors.Add("ProductType","Invalid product type"); - } - } - - public override Dictionary GetErrors() - { - return _errors; - } - } +using System; +using System.Collections.Generic; +using Nop.Core.Domain.Catalog; + +namespace Nop.Plugin.Api.Attributes +{ + public class ProductTypeValidationAttribute : BaseValidationAttribute + { + private readonly Dictionary _errors = new Dictionary(); + + public override void Validate(object instance) + { + // Product Type is not required so it could be null + // and there is nothing to validate in this case + if (instance == null) + return; + + var isDefined = Enum.IsDefined(typeof(ProductType), instance); + + if (!isDefined) + { + _errors.Add("ProductType","Invalid product type"); + } + } + + public override Dictionary GetErrors() + { + return _errors; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/ValidateVendor.cs b/Attributes/ValidateVendor.cs similarity index 96% rename from Nop.Plugin.Api/Attributes/ValidateVendor.cs rename to Attributes/ValidateVendor.cs index 3cebcad..7bc19b1 100644 --- a/Nop.Plugin.Api/Attributes/ValidateVendor.cs +++ b/Attributes/ValidateVendor.cs @@ -1,54 +1,54 @@ -using System.Collections.Generic; -using Nop.Core.Infrastructure; -using Nop.Services.Vendors; - -namespace Nop.Plugin.Api.Attributes -{ - public class ValidateVendor : BaseValidationAttribute - { - private Dictionary _errors; - - private IVendorService _vendorService; - - private IVendorService VendorService - { - get - { - if (_vendorService == null) - { - _vendorService = EngineContext.Current.Resolve(); - } - - return _vendorService; - } - } - - public ValidateVendor() - { - _errors = new Dictionary(); - } - - public override void Validate(object instance) - { - var vendorId = 0; - - if (instance != null && int.TryParse(instance.ToString(), out vendorId)) - { - if (vendorId > 0) - { - var vendor = VendorService.GetVendorById(vendorId); - - if (vendor == null) - { - _errors.Add("Invalid vendor id", "Non existing vendor"); - } - } - } - } - - public override Dictionary GetErrors() - { - return _errors; - } - } +using System.Collections.Generic; +using Nop.Core.Infrastructure; +using Nop.Services.Vendors; + +namespace Nop.Plugin.Api.Attributes +{ + public class ValidateVendor : BaseValidationAttribute + { + private Dictionary _errors; + + private IVendorService _vendorService; + + private IVendorService VendorService + { + get + { + if (_vendorService == null) + { + _vendorService = EngineContext.Current.Resolve(); + } + + return _vendorService; + } + } + + public ValidateVendor() + { + _errors = new Dictionary(); + } + + public override void Validate(object instance) + { + var vendorId = 0; + + if (instance != null && int.TryParse(instance.ToString(), out vendorId)) + { + if (vendorId > 0) + { + var vendor = VendorService.GetVendorById(vendorId); + + if (vendor == null) + { + _errors.Add("Invalid vendor id", "Non existing vendor"); + } + } + } + } + + public override Dictionary GetErrors() + { + return _errors; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Policies/ActiveApiPluginAuthorizationPolicy.cs b/Authorization/Policies/ActiveApiPluginAuthorizationPolicy.cs similarity index 100% rename from Nop.Plugin.Api/Authorization/Policies/ActiveApiPluginAuthorizationPolicy.cs rename to Authorization/Policies/ActiveApiPluginAuthorizationPolicy.cs diff --git a/Authorization/Policies/CustomerRoleAuthorizationPolicy.cs b/Authorization/Policies/CustomerRoleAuthorizationPolicy.cs new file mode 100644 index 0000000..ef50e04 --- /dev/null +++ b/Authorization/Policies/CustomerRoleAuthorizationPolicy.cs @@ -0,0 +1,36 @@ +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.KeyVault.Models; +using Nop.Plugin.Api.Authorization.Requirements; + +namespace Nop.Plugin.Api.Authorization.Policies +{ + public class CustomerRoleAuthorizationPolicy : AuthorizationHandler + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public CustomerRoleAuthorizationPolicy(IHttpContextAccessor httpContextAccessor) + { + this._httpContextAccessor = httpContextAccessor; + } + + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomerRoleRequirement requirement) + { + if (requirement.IsCustomerInRole()) + { + context.Succeed(requirement); + } + else + { + var message = Encoding.UTF8.GetBytes("User authenticated but not in Api Role."); + this._httpContextAccessor.HttpContext.Response.Body.WriteAsync(message); + context.Fail(); + } + + return Task.CompletedTask; + } + } +} diff --git a/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs b/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs new file mode 100644 index 0000000..35a556c --- /dev/null +++ b/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs @@ -0,0 +1,30 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Filters; +using Nop.Plugin.Api.Authorization.Requirements; + +namespace Nop.Plugin.Api.Authorization.Policies +{ + public class ValidSchemeAuthorizationPolicy : AuthorizationHandler + { + IHttpContextAccessor _httpContextAccessor = null; + public ValidSchemeAuthorizationPolicy(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizationSchemeRequirement requirement) + { + if (requirement.IsValid(_httpContextAccessor?.HttpContext.Request.Headers)) + { + context.Succeed(requirement); + } + else + { + context.Fail(); + } + + return Task.CompletedTask; + } + } +} diff --git a/Nop.Plugin.Api/Authorization/Requirements/ActiveApiPluginRequirement.cs b/Authorization/Requirements/ActiveApiPluginRequirement.cs similarity index 96% rename from Nop.Plugin.Api/Authorization/Requirements/ActiveApiPluginRequirement.cs rename to Authorization/Requirements/ActiveApiPluginRequirement.cs index 7ac1fce..1d911e5 100644 --- a/Nop.Plugin.Api/Authorization/Requirements/ActiveApiPluginRequirement.cs +++ b/Authorization/Requirements/ActiveApiPluginRequirement.cs @@ -1,21 +1,21 @@ -namespace Nop.Plugin.Api.Authorization.Requirements -{ - using Microsoft.AspNetCore.Authorization; - using Nop.Core.Infrastructure; - using Nop.Plugin.Api.Domain; - - public class ActiveApiPluginRequirement : IAuthorizationRequirement - { - public bool IsActive() - { - var settings = EngineContext.Current.Resolve(); - - if (settings.EnableApi) - { - return true; - } - - return false; - } - } +namespace Nop.Plugin.Api.Authorization.Requirements +{ + using Microsoft.AspNetCore.Authorization; + using Nop.Core.Infrastructure; + using Nop.Plugin.Api.Domain; + + public class ActiveApiPluginRequirement : IAuthorizationRequirement + { + public bool IsActive() + { + var settings = EngineContext.Current.Resolve(); + + if (settings.EnableApi) + { + return true; + } + + return false; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Requirements/AuthorizationSchemeRequirement.cs b/Authorization/Requirements/AuthorizationSchemeRequirement.cs similarity index 100% rename from Nop.Plugin.Api/Authorization/Requirements/AuthorizationSchemeRequirement.cs rename to Authorization/Requirements/AuthorizationSchemeRequirement.cs diff --git a/Authorization/Requirements/CustomerRoleRequirement.cs b/Authorization/Requirements/CustomerRoleRequirement.cs new file mode 100644 index 0000000..e5e28e1 --- /dev/null +++ b/Authorization/Requirements/CustomerRoleRequirement.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using MailKit.Security; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Nop.Core.Domain.Customers; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Infrastructure; +using Nop.Services.Customers; + +namespace Nop.Plugin.Api.Authorization.Requirements +{ + public class CustomerRoleRequirement : IAuthorizationRequirement + { + public bool IsCustomerInRole() + { + try + { + var httpContextAccessor = EngineContext.Current.Resolve(); + + var customerIdClaim = httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(m => m.Type == ClaimTypes.NameIdentifier); + + if (customerIdClaim != null && Guid.TryParse(customerIdClaim.Value, out var customerGuid)) + { + var customerService = EngineContext.Current.Resolve(); + + var customer = customerService.GetCustomerByGuid(customerGuid); + + if (customer != null) + { + var customerRoles = customerService.GetCustomerRoles(customer); + return IsInApiRole(customerRoles); + } + } + } + catch + { + // best effort + } + + return false; + } + + private static bool IsInApiRole(IEnumerable customerRoles) + { + return customerRoles.FirstOrDefault(cr => cr.SystemName == Constants.Roles.ApiRoleSystemName) != null; + } + } +} diff --git a/AutoMapper/ApiMapperConfiguration.cs b/AutoMapper/ApiMapperConfiguration.cs new file mode 100644 index 0000000..b598b61 --- /dev/null +++ b/AutoMapper/ApiMapperConfiguration.cs @@ -0,0 +1,196 @@ +using AutoMapper; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Common; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Localization; +using Nop.Core.Domain.Messages; +using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Stores; +using Nop.Core.Infrastructure.Mapper; +using Nop.Plugin.Api.Areas.Admin.Models; +using Nop.Plugin.Api.Domain; +using Nop.Plugin.Api.DTO; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.DTO.CustomerRoles; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.Languages; +using Nop.Plugin.Api.DTO.Manufacturers; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.DTO.Orders; +using Nop.Plugin.Api.DTO.ProductAttributes; +using Nop.Plugin.Api.DTO.ProductCategoryMappings; +using Nop.Plugin.Api.DTO.ProductManufacturerMappings; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using Nop.Plugin.Api.DTO.SpecificationAttributes; +using Nop.Plugin.Api.DTO.Stores; +using Nop.Plugin.Api.MappingExtensions; + +namespace Nop.Plugin.Api.AutoMapper +{ + public class ApiMapperConfiguration : Profile, IOrderedMapperProfile + { + public ApiMapperConfiguration() + { + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateClientToClientApiModelMap(); + + CreateAddressMap(); + CreateAddressDtoToEntityMap(); + CreateShoppingCartItemMap(); + + CreateCustomerToDTOMap(); + CreateCustomerToOrderCustomerDTOMap(); + CreateCustomerDTOToOrderCustomerDTOMap(); + CreateCustomerForShoppingCartItemMapFromCustomer(); + + CreateMap(); + CreateOrderEntityToOrderDtoMap(); + + CreateProductMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + } + + public int Order => 0; + + private new static void CreateMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting(); + } + + private static void CreateClientToClientApiModelMap() + { + //AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + // .ForMember(x => x.ClientSecret, y => y.MapFrom(src => src.ClientSecrets.FirstOrDefault().Description)) + // .ForMember(x => x.RedirectUrl, y => y.MapFrom(src => src.RedirectUris.FirstOrDefault().RedirectUri)) + // .ForMember(x => x.AccessTokenLifetime, y => y.MapFrom(src => src.AccessTokenLifetime)) + // .ForMember(x => x.RefreshTokenLifetime, y => y.MapFrom(src => src.AbsoluteRefreshTokenLifetime)); + } + + private void CreateOrderEntityToOrderDtoMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting() + .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); + //.ForMember(x => x.OrderItems, y => y.MapFrom(src => src.OrderItems.Select(x => x.ToDto()))); + } + + private void CreateAddressMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting() + .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); + //.ForMember(x => x.CountryName, + // y => y.MapFrom(src => src.Country.GetWithDefault(x => x, new Country()).Name)) + //.ForMember(x => x.StateProvinceName, + // y => y.MapFrom(src => src.StateProvince.GetWithDefault(x => x, new StateProvince()).Name)); + } + + private void CreateAddressDtoToEntityMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting() + .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); + } + + private void CreateCustomerForShoppingCartItemMapFromCustomer() + { + AutoMapperApiConfiguration.MapperConfigurationExpression + .CreateMap() + .IgnoreAllNonExisting() + .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); + //.ForMember(x => x.BillingAddress, + // y => y.MapFrom(src => src.BillingAddress.GetWithDefault(x => x, new Address()).ToDto())) + //.ForMember(x => x.ShippingAddress, + // y => y.MapFrom(src => src.ShippingAddress.GetWithDefault(x => x, new Address()).ToDto())) + //.ForMember(x => x.Addresses, + // y => y.MapFrom(src => + // src.Addresses.GetWithDefault(x => x, new List
()).Select(address => address.ToDto()))); + } + + private void CreateCustomerToDTOMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting() + .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); + //.ForMember(x => x.BillingAddress, + // y => y.MapFrom(src => src.BillingAddress.GetWithDefault(x => x, new Address()).ToDto())) + //.ForMember(x => x.ShippingAddress, + // y => y.MapFrom(src => src.ShippingAddress.GetWithDefault(x => x, new Address()).ToDto())) + //.ForMember(x => x.Addresses, + // y => + // y.MapFrom( + // src => + // src.Addresses.GetWithDefault(x => x, new List
()) + // .Select(address => address.ToDto()))) + //.ForMember(x => x.ShoppingCartItems, + // y => + // y.MapFrom( + // src => + // src.ShoppingCartItems.GetWithDefault(x => x, new List()) + // .Select(item => item.ToDto()))) + //.ForMember(x => x.RoleIds, y => y.MapFrom(src => src.CustomerRoles.Select(z => z.Id))); + } + + private void CreateCustomerToOrderCustomerDTOMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting(); + } + + private void CreateCustomerDTOToOrderCustomerDTOMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting(); + } + + private void CreateShoppingCartItemMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting(); + //.ForMember(x => x.CustomerDto, + // y => y.MapFrom(src => + // src.Customer.GetWithDefault(x => x, new Customer()).ToCustomerForShoppingCartItemDto())) + //.ForMember(x => x.ProductDto, + // y => y.MapFrom(src => src.Product.GetWithDefault(x => x, new Product()).ToDto())); + } + + private void CreateProductMap() + { + AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() + .IgnoreAllNonExisting(); + //.ForMember(x => x.FullDescription, y => y.MapFrom(src => WebUtility.HtmlEncode(src.FullDescription))) + //.ForMember(x => x.Tags, + // y => y.MapFrom(src => src.ProductProductTagMappings.Select(x => x.ProductTag.Name))); + } + } +} diff --git a/Nop.Plugin.Api/AutoMapper/AutoMapperApiConfiguration.cs b/AutoMapper/AutoMapperApiConfiguration.cs similarity index 83% rename from Nop.Plugin.Api/AutoMapper/AutoMapperApiConfiguration.cs rename to AutoMapper/AutoMapperApiConfiguration.cs index 93291b5..e19c1fa 100644 --- a/Nop.Plugin.Api/AutoMapper/AutoMapperApiConfiguration.cs +++ b/AutoMapper/AutoMapperApiConfiguration.cs @@ -1,46 +1,47 @@ -using AutoMapper; -using AutoMapper.Configuration; - -namespace Nop.Plugin.Api.AutoMapper -{ - public static class AutoMapperApiConfiguration - { - private static MapperConfigurationExpression s_mapperConfigurationExpression; - private static IMapper s_mapper; - private static readonly object s_mapperLockObject = new object(); - - public static MapperConfigurationExpression MapperConfigurationExpression => s_mapperConfigurationExpression ?? - (s_mapperConfigurationExpression = new MapperConfigurationExpression()); - - public static IMapper Mapper - { - get - { - if (s_mapper == null) - { - lock (s_mapperLockObject) - { - if (s_mapper == null) - { - var mapperConfiguration = new MapperConfiguration(MapperConfigurationExpression); - - s_mapper = mapperConfiguration.CreateMapper(); - } - } - } - - return s_mapper; - } - } - - public static TDestination MapTo(this TSource source) - { - return Mapper.Map(source); - } - - public static TDestination MapTo(this TSource source, TDestination destination) - { - return Mapper.Map(source, destination); - } - } -} \ No newline at end of file +using AutoMapper; +using AutoMapper.Configuration; + +namespace Nop.Plugin.Api.AutoMapper +{ + public static class AutoMapperApiConfiguration + { + private static MapperConfigurationExpression s_mapperConfigurationExpression; + private static IMapper s_mapper; + private static readonly object s_mapperLockObject = new object(); + + public static MapperConfigurationExpression MapperConfigurationExpression => + s_mapperConfigurationExpression ?? + (s_mapperConfigurationExpression = new MapperConfigurationExpression()); + + public static IMapper Mapper + { + get + { + if (s_mapper == null) + { + lock (s_mapperLockObject) + { + if (s_mapper == null) + { + var mapperConfiguration = new MapperConfiguration(MapperConfigurationExpression); + + s_mapper = mapperConfiguration.CreateMapper(); + } + } + } + + return s_mapper; + } + } + + public static TDestination MapTo(this TSource source) + { + return Mapper.Map(source); + } + + public static TDestination MapTo(this TSource source, TDestination destination) + { + return Mapper.Map(source, destination); + } + } +} diff --git a/Configuration/ApiConfiguration.cs b/Configuration/ApiConfiguration.cs new file mode 100644 index 0000000..546ceda --- /dev/null +++ b/Configuration/ApiConfiguration.cs @@ -0,0 +1,9 @@ +namespace Nop.Plugin.Api.Configuration +{ + public class ApiConfiguration + { + public int AllowedClockSkewInMinutes { get; set; } = 5; + + public string SecurityKey { get; set; } = "NowIsTheTimeForAllGoodMenToComeToTheAideOfTheirCountry"; + } +} diff --git a/Configuration/ApplicationPartsLogger.cs b/Configuration/ApplicationPartsLogger.cs new file mode 100644 index 0000000..d27c751 --- /dev/null +++ b/Configuration/ApplicationPartsLogger.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.ApplicationParts; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Nop.Plugin.Api.Configuration +{ + public class ApplicationPartsLogger : IHostedService + { + private readonly ILogger _logger; + private readonly ApplicationPartManager _partManager; + + public ApplicationPartsLogger(ILogger logger, ApplicationPartManager partManager) + { + _logger = logger; + _partManager = partManager; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + // Get the names of all the application parts. This is the short assembly name for AssemblyParts + var applicationParts = _partManager.ApplicationParts.Select(x => x.Name); + + // Create a controller feature, and populate it from the application parts + var controllerFeature = new ControllerFeature(); + _partManager.PopulateFeature(controllerFeature); + + // Get the names of all of the controllers + var controllers = controllerFeature.Controllers.Select(x => x.Name); + + // Log the application parts and controllers + _logger.LogInformation("Found the following application parts: '{ApplicationParts}' with the following controllers: '{Controllers}'", + string.Join(", ", applicationParts), string.Join(", ", controllers)); + + return Task.CompletedTask; + } + + // Required by the interface + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } +} diff --git a/Nop.Plugin.Api/Controllers/BaseApiController.cs b/Controllers/BaseApiController.cs similarity index 94% rename from Nop.Plugin.Api/Controllers/BaseApiController.cs rename to Controllers/BaseApiController.cs index 85ed195..47d7cd4 100644 --- a/Nop.Plugin.Api/Controllers/BaseApiController.cs +++ b/Controllers/BaseApiController.cs @@ -1,152 +1,155 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core; -using Nop.Core.Domain.Security; -using Nop.Core.Domain.Stores; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; -using Microsoft.AspNetCore.Mvc; - -namespace Nop.Plugin.Api.Controllers -{ - using JSON.Serializers; - - public class BaseApiController : Controller - { - protected readonly IJsonFieldsSerializer JsonFieldsSerializer; - protected readonly IAclService AclService; - protected readonly ICustomerService CustomerService; - protected readonly IStoreMappingService StoreMappingService; - protected readonly IStoreService StoreService; - protected readonly IDiscountService DiscountService; - protected readonly ICustomerActivityService CustomerActivityService; - protected readonly ILocalizationService LocalizationService; - protected readonly IPictureService PictureService; - - public BaseApiController(IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService) - { - JsonFieldsSerializer = jsonFieldsSerializer; - AclService = aclService; - CustomerService = customerService; - StoreMappingService = storeMappingService; - StoreService = storeService; - DiscountService = discountService; - CustomerActivityService = customerActivityService; - LocalizationService = localizationService; - PictureService = pictureService; - } - - protected IActionResult Error(HttpStatusCode statusCode = (HttpStatusCode)422, string propertyKey = "", string errorMessage = "") - { - var errors = new Dictionary>(); - - if (!string.IsNullOrEmpty(errorMessage) && !string.IsNullOrEmpty(propertyKey)) - { - var errorsList = new List() {errorMessage}; - errors.Add(propertyKey, errorsList); - } - - foreach (var item in ModelState) - { - var errorMessages = item.Value.Errors.Select(x => x.ErrorMessage); - - var validErrorMessages = new List(); - - validErrorMessages.AddRange(errorMessages.Where(message => !string.IsNullOrEmpty(message))); - - if (validErrorMessages.Count > 0) - { - if (errors.ContainsKey(item.Key)) - { - errors[item.Key].AddRange(validErrorMessages); - } - else - { - errors.Add(item.Key, validErrorMessages.ToList()); - } - } - } - - var errorsRootObject = new ErrorsRootObject() - { - Errors = errors - }; - - var errorsJson = JsonFieldsSerializer.Serialize(errorsRootObject, null); - - return new ErrorActionResult(errorsJson, statusCode); - } - - protected void UpdateAclRoles(TEntity entity, List passedRoleIds) where TEntity: BaseEntity, IAclSupported - { - if (passedRoleIds == null) - { - return; - } - - entity.SubjectToAcl = passedRoleIds.Any(); - - var existingAclRecords = AclService.GetAclRecords(entity); - var allCustomerRoles = CustomerService.GetAllCustomerRoles(true); - foreach (var customerRole in allCustomerRoles) - { - if (passedRoleIds.Contains(customerRole.Id)) - { - //new role - if (existingAclRecords.Count(acl => acl.CustomerRoleId == customerRole.Id) == 0) - AclService.InsertAclRecord(entity, customerRole.Id); - } - else - { - //remove role - var aclRecordToDelete = existingAclRecords.FirstOrDefault(acl => acl.CustomerRoleId == customerRole.Id); - if (aclRecordToDelete != null) - AclService.DeleteAclRecord(aclRecordToDelete); - } - } - } - - protected void UpdateStoreMappings(TEntity entity, List passedStoreIds) where TEntity : BaseEntity, IStoreMappingSupported - { - if(passedStoreIds == null) - return; - - entity.LimitedToStores = passedStoreIds.Any(); - - var existingStoreMappings = StoreMappingService.GetStoreMappings(entity); - var allStores = StoreService.GetAllStores(); - foreach (var store in allStores) - { - if (passedStoreIds.Contains(store.Id)) - { - //new store - if (existingStoreMappings.Count(sm => sm.StoreId == store.Id) == 0) - StoreMappingService.InsertStoreMapping(entity, store.Id); - } - else - { - //remove store - var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id); - if (storeMappingToDelete != null) - StoreMappingService.DeleteStoreMapping(storeMappingToDelete); - } - } - } - } +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Nop.Core; +using Nop.Core.Domain.Security; +using Nop.Core.Domain.Stores; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Nop.Plugin.Api.JSON.Serializers; + +namespace Nop.Plugin.Api.Controllers +{ + [ApiController] + [Authorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + public class BaseApiController : Controller + { + protected readonly IJsonFieldsSerializer JsonFieldsSerializer; + protected readonly IAclService AclService; + protected readonly ICustomerService CustomerService; + protected readonly IStoreMappingService StoreMappingService; + protected readonly IStoreService StoreService; + protected readonly IDiscountService DiscountService; + protected readonly ICustomerActivityService CustomerActivityService; + protected readonly ILocalizationService LocalizationService; + protected readonly IPictureService PictureService; + + public BaseApiController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService) + { + JsonFieldsSerializer = jsonFieldsSerializer; + AclService = aclService; + CustomerService = customerService; + StoreMappingService = storeMappingService; + StoreService = storeService; + DiscountService = discountService; + CustomerActivityService = customerActivityService; + LocalizationService = localizationService; + PictureService = pictureService; + } + + protected IActionResult Error(HttpStatusCode statusCode = (HttpStatusCode)422, string propertyKey = "", string errorMessage = "") + { + var errors = new Dictionary>(); + + if (!string.IsNullOrEmpty(errorMessage) && !string.IsNullOrEmpty(propertyKey)) + { + var errorsList = new List() {errorMessage}; + errors.Add(propertyKey, errorsList); + } + + foreach (var item in ModelState) + { + var errorMessages = item.Value.Errors.Select(x => x.ErrorMessage); + + var validErrorMessages = new List(); + + validErrorMessages.AddRange(errorMessages.Where(message => !string.IsNullOrEmpty(message))); + + if (validErrorMessages.Count > 0) + { + if (errors.ContainsKey(item.Key)) + { + errors[item.Key].AddRange(validErrorMessages); + } + else + { + errors.Add(item.Key, validErrorMessages.ToList()); + } + } + } + + var errorsRootObject = new ErrorsRootObject() + { + Errors = errors + }; + + var errorsJson = JsonFieldsSerializer.Serialize(errorsRootObject, null); + + return new ErrorActionResult(errorsJson, statusCode); + } + + protected void UpdateAclRoles(TEntity entity, List passedRoleIds) where TEntity: BaseEntity, IAclSupported + { + if (passedRoleIds == null) + { + return; + } + + entity.SubjectToAcl = passedRoleIds.Any(); + + var existingAclRecords = AclService.GetAclRecords(entity); + var allCustomerRoles = CustomerService.GetAllCustomerRoles(true); + foreach (var customerRole in allCustomerRoles) + { + if (passedRoleIds.Contains(customerRole.Id)) + { + //new role + if (existingAclRecords.Count(acl => acl.CustomerRoleId == customerRole.Id) == 0) + AclService.InsertAclRecord(entity, customerRole.Id); + } + else + { + //remove role + var aclRecordToDelete = existingAclRecords.FirstOrDefault(acl => acl.CustomerRoleId == customerRole.Id); + if (aclRecordToDelete != null) + AclService.DeleteAclRecord(aclRecordToDelete); + } + } + } + + protected void UpdateStoreMappings(TEntity entity, List passedStoreIds) where TEntity : BaseEntity, IStoreMappingSupported + { + if(passedStoreIds == null) + return; + + entity.LimitedToStores = passedStoreIds.Any(); + + var existingStoreMappings = StoreMappingService.GetStoreMappings(entity); + var allStores = StoreService.GetAllStores(); + foreach (var store in allStores) + { + if (passedStoreIds.Contains(store.Id)) + { + //new store + if (existingStoreMappings.Count(sm => sm.StoreId == store.Id) == 0) + StoreMappingService.InsertStoreMapping(entity, store.Id); + } + else + { + //remove store + var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id); + if (storeMappingToDelete != null) + StoreMappingService.DeleteStoreMapping(storeMappingToDelete); + } + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/CategoriesController.cs b/Controllers/CategoriesController.cs similarity index 90% rename from Nop.Plugin.Api/Controllers/CategoriesController.cs rename to Controllers/CategoriesController.cs index 32e0870..67c3e07 100644 --- a/Nop.Plugin.Api/Controllers/CategoriesController.cs +++ b/Controllers/CategoriesController.cs @@ -1,390 +1,389 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Discounts; -using Nop.Core.Domain.Media; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.Models.CategoriesParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Seo; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.Factories; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.ModelBinders; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; -using Nop.Plugin.Api.Helpers; -using Microsoft.AspNetCore.Mvc; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class CategoriesController : BaseApiController - { - private readonly ICategoryApiService _categoryApiService; - private readonly ICategoryService _categoryService; - private readonly IUrlRecordService _urlRecordService; - private readonly IFactory _factory; - private readonly IDTOHelper _dtoHelper; - - public CategoriesController(ICategoryApiService categoryApiService, - IJsonFieldsSerializer jsonFieldsSerializer, - ICategoryService categoryService, - IUrlRecordService urlRecordService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - IAclService aclService, - ICustomerService customerService, - IFactory factory, - IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService,pictureService) - { - _categoryApiService = categoryApiService; - _categoryService = categoryService; - _urlRecordService = urlRecordService; - _factory = factory; - _dtoHelper = dtoHelper; - } - - /// - /// Receive a list of all Categories - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/categories")] - [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCategories(CategoriesParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); - } - - var allCategories = _categoryApiService.GetCategories(parameters.Ids, parameters.CreatedAtMin, parameters.CreatedAtMax, - parameters.UpdatedAtMin, parameters.UpdatedAtMax, - parameters.Limit, parameters.Page, parameters.SinceId, - parameters.ProductId, parameters.PublishedStatus) - .Where(c => StoreMappingService.Authorize(c)); - - IList categoriesAsDtos = allCategories.Select(category => - { - return _dtoHelper.PrepareCategoryDTO(category); - - }).ToList(); - - var categoriesRootObject = new CategoriesRootObject() - { - Categories = categoriesAsDtos - }; - - var json = JsonFieldsSerializer.Serialize(categoriesRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a count of all Categories - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/categories/count")] - [ProducesResponseType(typeof(CategoriesCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCategoriesCount(CategoriesCountParametersModel parameters) - { - var allCategoriesCount = _categoryApiService.GetCategoriesCount(parameters.CreatedAtMin, parameters.CreatedAtMax, - parameters.UpdatedAtMin, parameters.UpdatedAtMax, - parameters.PublishedStatus, parameters.ProductId); - - var categoriesCountRootObject = new CategoriesCountRootObject() - { - Count = allCategoriesCount - }; - - return Ok(categoriesCountRootObject); - } - - /// - /// Retrieve category by spcified id - /// - /// Id of the category - /// Fields from the category you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/categories/{id}")] - [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCategoryById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var category = _categoryApiService.GetCategoryById(id); - - if (category == null) - { - return Error(HttpStatusCode.NotFound, "category", "category not found"); - } - - var categoryDto = _dtoHelper.PrepareCategoryDTO(category); - - var categoriesRootObject = new CategoriesRootObject(); - - categoriesRootObject.Categories.Add(categoryDto); - - var json = JsonFieldsSerializer.Serialize(categoriesRootObject, fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/categories")] - [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult CreateCategory([ModelBinder(typeof(JsonModelBinder))] Delta categoryDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - //If the validation has passed the categoryDelta object won't be null for sure so we don't need to check for this. - - Picture insertedPicture = null; - - // We need to insert the picture before the category so we can obtain the picture id and map it to the category. - if (categoryDelta.Dto.Image != null && categoryDelta.Dto.Image.Binary != null) - { - insertedPicture = PictureService.InsertPicture(categoryDelta.Dto.Image.Binary, categoryDelta.Dto.Image.MimeType, string.Empty); - } - - // Inserting the new category - var category = _factory.Initialize(); - categoryDelta.Merge(category); - - if (insertedPicture != null) - { - category.PictureId = insertedPicture.Id; - } - - _categoryService.InsertCategory(category); - - - UpdateAclRoles(category, categoryDelta.Dto.RoleIds); - - UpdateDiscounts(category, categoryDelta.Dto.DiscountIds); - - UpdateStoreMappings(category, categoryDelta.Dto.StoreIds); - - //search engine name - if (categoryDelta.Dto.SeName != null) - { - var seName = _urlRecordService.ValidateSeName(category, categoryDelta.Dto.SeName, category.Name, true); - _urlRecordService.SaveSlug(category, seName, 0); - } - - CustomerActivityService.InsertActivity("AddNewCategory", - LocalizationService.GetResource("ActivityLog.AddNewCategory"), category); - - // Preparing the result dto of the new category - var newCategoryDto = _dtoHelper.PrepareCategoryDTO(category); - - var categoriesRootObject = new CategoriesRootObject(); - - categoriesRootObject.Categories.Add(newCategoryDto); - - var json = JsonFieldsSerializer.Serialize(categoriesRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/categories/{id}")] - [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - public IActionResult UpdateCategory( - [ModelBinder(typeof (JsonModelBinder))] Delta categoryDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var category = _categoryApiService.GetCategoryById(categoryDelta.Dto.Id); - - if (category == null) - { - return Error(HttpStatusCode.NotFound, "category", "category not found"); - } - - categoryDelta.Merge(category); - - category.UpdatedOnUtc = DateTime.UtcNow; - - _categoryService.UpdateCategory(category); - - UpdatePicture(category, categoryDelta.Dto.Image); - - UpdateAclRoles(category, categoryDelta.Dto.RoleIds); - - UpdateDiscounts(category, categoryDelta.Dto.DiscountIds); - - UpdateStoreMappings(category, categoryDelta.Dto.StoreIds); - - //search engine name - if (categoryDelta.Dto.SeName != null) - { - - var seName = _urlRecordService.ValidateSeName(category, categoryDelta.Dto.SeName, category.Name, true); - _urlRecordService.SaveSlug(category, seName, 0); - } - - _categoryService.UpdateCategory(category); - - CustomerActivityService.InsertActivity("UpdateCategory", - LocalizationService.GetResource("ActivityLog.UpdateCategory"), category); - - var categoryDto = _dtoHelper.PrepareCategoryDTO(category); - - var categoriesRootObject = new CategoriesRootObject(); - - categoriesRootObject.Categories.Add(categoryDto); - - var json = JsonFieldsSerializer.Serialize(categoriesRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/categories/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteCategory(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var categoryToDelete = _categoryApiService.GetCategoryById(id); - - if (categoryToDelete == null) - { - return Error(HttpStatusCode.NotFound, "category", "category not found"); - } - - _categoryService.DeleteCategory(categoryToDelete); - - //activity log - CustomerActivityService.InsertActivity("DeleteCategory", LocalizationService.GetResource("ActivityLog.DeleteCategory"), categoryToDelete); - - return new RawJsonActionResult("{}"); - } - - private void UpdatePicture(Category categoryEntityToUpdate, ImageDto imageDto) - { - // no image specified then do nothing - if (imageDto == null) - return; - - Picture updatedPicture; - var currentCategoryPicture = PictureService.GetPictureById(categoryEntityToUpdate.PictureId); - - // when there is a picture set for the category - if (currentCategoryPicture != null) - { - PictureService.DeletePicture(currentCategoryPicture); - - // When the image attachment is null or empty. - if (imageDto.Binary == null) - { - categoryEntityToUpdate.PictureId = 0; - } - else - { - updatedPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); - categoryEntityToUpdate.PictureId = updatedPicture.Id; - } - } - // when there isn't a picture set for the category - else - { - if (imageDto.Binary != null) - { - updatedPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); - categoryEntityToUpdate.PictureId = updatedPicture.Id; - } - } - } - - private void UpdateDiscounts(Category category, List passedDiscountIds) - { - if(passedDiscountIds == null) - return; - - var allDiscounts = DiscountService.GetAllDiscounts(DiscountType.AssignedToCategories, showHidden: true); - foreach (var discount in allDiscounts) - { - if (passedDiscountIds.Contains(discount.Id)) - { - //new discount - if (category.AppliedDiscounts.Count(d => d.Id == discount.Id) == 0) - category.AppliedDiscounts.Add(discount); - } - else - { - //remove discount - if (category.AppliedDiscounts.Count(d => d.Id == discount.Id) > 0) - category.AppliedDiscounts.Remove(discount); - } - } - _categoryService.UpdateCategory(category); - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Discounts; +using Nop.Core.Domain.Media; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.CategoriesParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Seo; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class CategoriesController : BaseApiController + { + private readonly ICategoryApiService _categoryApiService; + private readonly ICategoryService _categoryService; + private readonly IUrlRecordService _urlRecordService; + private readonly IFactory _factory; + private readonly IDTOHelper _dtoHelper; + + public CategoriesController(ICategoryApiService categoryApiService, + IJsonFieldsSerializer jsonFieldsSerializer, + ICategoryService categoryService, + IUrlRecordService urlRecordService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + IAclService aclService, + ICustomerService customerService, + IFactory factory, + IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService,pictureService) + { + _categoryApiService = categoryApiService; + _categoryService = categoryService; + _urlRecordService = urlRecordService; + _factory = factory; + _dtoHelper = dtoHelper; + } + + /// + /// Receive a list of all Categories + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/categories")] + [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCategories(CategoriesParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); + } + + var allCategories = _categoryApiService.GetCategories(parameters.Ids, parameters.CreatedAtMin, parameters.CreatedAtMax, + parameters.UpdatedAtMin, parameters.UpdatedAtMax, + parameters.Limit, parameters.Page, parameters.SinceId, + parameters.ProductId, parameters.PublishedStatus) + .Where(c => StoreMappingService.Authorize(c)); + + IList categoriesAsDtos = allCategories.Select(category => + { + return _dtoHelper.PrepareCategoryDTO(category); + + }).ToList(); + + var categoriesRootObject = new CategoriesRootObject() + { + Categories = categoriesAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(categoriesRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a count of all Categories + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/categories/count")] + [ProducesResponseType(typeof(CategoriesCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCategoriesCount(CategoriesCountParametersModel parameters) + { + var allCategoriesCount = _categoryApiService.GetCategoriesCount(parameters.CreatedAtMin, parameters.CreatedAtMax, + parameters.UpdatedAtMin, parameters.UpdatedAtMax, + parameters.PublishedStatus, parameters.ProductId); + + var categoriesCountRootObject = new CategoriesCountRootObject() + { + Count = allCategoriesCount + }; + + return Ok(categoriesCountRootObject); + } + + /// + /// Retrieve category by spcified id + /// + /// Id of the category + /// Fields from the category you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/categories/{id}")] + [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCategoryById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var category = _categoryApiService.GetCategoryById(id); + + if (category == null) + { + return Error(HttpStatusCode.NotFound, "category", "category not found"); + } + + var categoryDto = _dtoHelper.PrepareCategoryDTO(category); + + var categoriesRootObject = new CategoriesRootObject(); + + categoriesRootObject.Categories.Add(categoryDto); + + var json = JsonFieldsSerializer.Serialize(categoriesRootObject, fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/categories")] + [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult CreateCategory([ModelBinder(typeof(JsonModelBinder))] Delta categoryDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + //If the validation has passed the categoryDelta object won't be null for sure so we don't need to check for this. + + Picture insertedPicture = null; + + // We need to insert the picture before the category so we can obtain the picture id and map it to the category. + if (categoryDelta.Dto.Image != null && categoryDelta.Dto.Image.Binary != null) + { + insertedPicture = PictureService.InsertPicture(categoryDelta.Dto.Image.Binary, categoryDelta.Dto.Image.MimeType, string.Empty); + } + + // Inserting the new category + var category = _factory.Initialize(); + categoryDelta.Merge(category); + + if (insertedPicture != null) + { + category.PictureId = insertedPicture.Id; + } + + _categoryService.InsertCategory(category); + + + UpdateAclRoles(category, categoryDelta.Dto.RoleIds); + + UpdateDiscounts(category, categoryDelta.Dto.DiscountIds); + + UpdateStoreMappings(category, categoryDelta.Dto.StoreIds); + + var seName = _urlRecordService.ValidateSeName(category, categoryDelta.Dto.SeName, category.Name, true); + _urlRecordService.SaveSlug(category, seName, 0); + + CustomerActivityService.InsertActivity("AddNewCategory", LocalizationService.GetResource("ActivityLog.AddNewCategory"), category); + + // Preparing the result dto of the new category + var newCategoryDto = _dtoHelper.PrepareCategoryDTO(category); + + var categoriesRootObject = new CategoriesRootObject(); + + categoriesRootObject.Categories.Add(newCategoryDto); + + var json = JsonFieldsSerializer.Serialize(categoriesRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/categories/{id}")] + [ProducesResponseType(typeof(CategoriesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + public IActionResult UpdateCategory( + [ModelBinder(typeof (JsonModelBinder))] Delta categoryDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var category = _categoryApiService.GetCategoryById(categoryDelta.Dto.Id); + + if (category == null) + { + return Error(HttpStatusCode.NotFound, "category", "category not found"); + } + + categoryDelta.Merge(category); + + category.UpdatedOnUtc = DateTime.UtcNow; + + _categoryService.UpdateCategory(category); + + UpdatePicture(category, categoryDelta.Dto.Image); + + UpdateAclRoles(category, categoryDelta.Dto.RoleIds); + + UpdateDiscounts(category, categoryDelta.Dto.DiscountIds); + + UpdateStoreMappings(category, categoryDelta.Dto.StoreIds); + + //search engine name + //if (categoryDelta.Dto.SeName != null) + //{ + + var seName = _urlRecordService.ValidateSeName(category, categoryDelta.Dto.SeName, category.Name, true); + _urlRecordService.SaveSlug(category, seName, 0); + //} + + _categoryService.UpdateCategory(category); + + CustomerActivityService.InsertActivity("UpdateCategory", + LocalizationService.GetResource("ActivityLog.UpdateCategory"), category); + + var categoryDto = _dtoHelper.PrepareCategoryDTO(category); + + var categoriesRootObject = new CategoriesRootObject(); + + categoriesRootObject.Categories.Add(categoryDto); + + var json = JsonFieldsSerializer.Serialize(categoriesRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/categories/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteCategory(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var categoryToDelete = _categoryApiService.GetCategoryById(id); + + if (categoryToDelete == null) + { + return Error(HttpStatusCode.NotFound, "category", "category not found"); + } + + _categoryService.DeleteCategory(categoryToDelete); + + //activity log + CustomerActivityService.InsertActivity("DeleteCategory", LocalizationService.GetResource("ActivityLog.DeleteCategory"), categoryToDelete); + + return new RawJsonActionResult("{}"); + } + + private void UpdatePicture(Category categoryEntityToUpdate, ImageDto imageDto) + { + // no image specified then do nothing + if (imageDto == null) + return; + + Picture updatedPicture; + var currentCategoryPicture = PictureService.GetPictureById(categoryEntityToUpdate.PictureId); + + // when there is a picture set for the category + if (currentCategoryPicture != null) + { + PictureService.DeletePicture(currentCategoryPicture); + + // When the image attachment is null or empty. + if (imageDto.Binary == null) + { + categoryEntityToUpdate.PictureId = 0; + } + else + { + updatedPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); + categoryEntityToUpdate.PictureId = updatedPicture.Id; + } + } + // when there isn't a picture set for the category + else + { + if (imageDto.Binary != null) + { + updatedPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); + categoryEntityToUpdate.PictureId = updatedPicture.Id; + } + } + } + + private void UpdateDiscounts(Category category, List passedDiscountIds) + { + if (passedDiscountIds == null) + { + return; + } + + var allDiscounts = DiscountService.GetAllDiscounts(DiscountType.AssignedToCategories, showHidden: true); + var appliedCategoryDiscount = DiscountService.GetAppliedDiscounts(category); + foreach (var discount in allDiscounts) + { + if (passedDiscountIds.Contains(discount.Id)) + { + //new discount + if (appliedCategoryDiscount.Count(d => d.Id == discount.Id) == 0) + { + appliedCategoryDiscount.Add(discount); + } + } + else + { + //remove discount + if (appliedCategoryDiscount.Count(d => d.Id == discount.Id) > 0) + { + appliedCategoryDiscount.Remove(discount); + } + } + } + _categoryService.UpdateCategory(category); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/CustomerRolesController.cs b/Controllers/CustomerRolesController.cs similarity index 84% rename from Nop.Plugin.Api/Controllers/CustomerRolesController.cs rename to Controllers/CustomerRolesController.cs index 1c054db..b793052 100644 --- a/Nop.Plugin.Api/Controllers/CustomerRolesController.cs +++ b/Controllers/CustomerRolesController.cs @@ -1,76 +1,73 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.CustomerRoles; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Controllers -{ - using System.Net; - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class CustomerRolesController : BaseApiController - { - public CustomerRolesController( - IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService) - : base(jsonFieldsSerializer, - aclService, - customerService, - storeMappingService, - storeService, - discountService, - customerActivityService, - localizationService, - pictureService) - { - } - - /// - /// Retrieve all customer roles - /// - /// Fields from the customer role you want your json to contain - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/customer_roles")] - [ProducesResponseType(typeof(CustomerRolesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetAllCustomerRoles(string fields = "") - { - var allCustomerRoles = CustomerService.GetAllCustomerRoles(); - - IList customerRolesAsDto = allCustomerRoles.Select(role => role.ToDto()).ToList(); - - var customerRolesRootObject = new CustomerRolesRootObject() - { - CustomerRoles = customerRolesAsDto - }; - - var json = JsonFieldsSerializer.Serialize(customerRolesRootObject, fields); - - return new RawJsonActionResult(json); - } - } -} +using Microsoft.AspNetCore.Mvc; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.CustomerRoles; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Nop.Plugin.Api.Controllers +{ + public class CustomerRolesController : BaseApiController + { + public CustomerRolesController( + IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService) + : base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + } + + /// + /// Retrieve all customer roles + /// + /// Fields from the customer role you want your json to contain + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/customer_roles")] + [ProducesResponseType(typeof(CustomerRolesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetAllCustomerRoles(string fields = "") + { + var allCustomerRoles = CustomerService.GetAllCustomerRoles(); + + IList customerRolesAsDto = allCustomerRoles.Select(role => role.ToDto()).ToList(); + + var customerRolesRootObject = new CustomerRolesRootObject() + { + CustomerRoles = customerRolesAsDto + }; + + var json = JsonFieldsSerializer.Serialize(customerRolesRootObject, fields); + + return new RawJsonActionResult(json); + } + } +} diff --git a/Nop.Plugin.Api/Controllers/CustomersController.cs b/Controllers/CustomersController.cs similarity index 85% rename from Nop.Plugin.Api/Controllers/CustomersController.cs rename to Controllers/CustomersController.cs index 0b9a81c..24c881c 100644 --- a/Nop.Plugin.Api/Controllers/CustomersController.cs +++ b/Controllers/CustomersController.cs @@ -1,561 +1,591 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core.Domain.Customers; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Factories; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.CustomersParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Common; -using Nop.Services.Customers; -using Nop.Services.Directory; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Messages; -using Nop.Services.Security; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class CustomersController : BaseApiController - { - private readonly ICustomerApiService _customerApiService; - private readonly ICustomerRolesHelper _customerRolesHelper; - private readonly IGenericAttributeService _genericAttributeService; - private readonly IEncryptionService _encryptionService; - private readonly ICountryService _countryService; - private readonly IMappingHelper _mappingHelper; - private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; - private readonly ILanguageService _languageService; - private readonly IFactory _factory; - - // We resolve the customer settings this way because of the tests. - // The auto mocking does not support concreate types as dependencies. It supports only interfaces. - private CustomerSettings _customerSettings; - - private CustomerSettings CustomerSettings - { - get - { - if (_customerSettings == null) - { - _customerSettings = EngineContext.Current.Resolve(); - } - - return _customerSettings; - } - } - - public CustomersController( - ICustomerApiService customerApiService, - IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - ICustomerRolesHelper customerRolesHelper, - IGenericAttributeService genericAttributeService, - IEncryptionService encryptionService, - IFactory factory, - ICountryService countryService, - IMappingHelper mappingHelper, - INewsLetterSubscriptionService newsLetterSubscriptionService, - IPictureService pictureService, ILanguageService languageService) : - base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService,pictureService) - { - _customerApiService = customerApiService; - _factory = factory; - _countryService = countryService; - _mappingHelper = mappingHelper; - _newsLetterSubscriptionService = newsLetterSubscriptionService; - _languageService = languageService; - _encryptionService = encryptionService; - _genericAttributeService = genericAttributeService; - _customerRolesHelper = customerRolesHelper; - } - - /// - /// Retrieve all customers of a shop - /// - /// OK - /// Bad request - /// Unauthorized - [HttpGet] - [Route("/api/customers")] - [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCustomers(CustomersParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid request parameters"); - } - - var allCustomers = _customerApiService.GetCustomersDtos(parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.Limit, parameters.Page, parameters.SinceId); - - var customersRootObject = new CustomersRootObject() - { - Customers = allCustomers - }; - - var json = JsonFieldsSerializer.Serialize(customersRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Retrieve customer by spcified id - /// - /// Id of the customer - /// Fields from the customer you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/customers/{id}")] - [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCustomerById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var customer = _customerApiService.GetCustomerById(id); - - if (customer == null) - { - return Error(HttpStatusCode.NotFound, "customer", "not found"); - } - - var customersRootObject = new CustomersRootObject(); - customersRootObject.Customers.Add(customer); - - var json = JsonFieldsSerializer.Serialize(customersRootObject, fields); - - return new RawJsonActionResult(json); - } - - - /// - /// Get a count of all customers - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/customers/count")] - [ProducesResponseType(typeof(CustomersCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - public IActionResult GetCustomersCount() - { - var allCustomersCount = _customerApiService.GetCustomersCount(); - - var customersCountRootObject = new CustomersCountRootObject() - { - Count = allCustomersCount - }; - - return Ok(customersCountRootObject); - } - - /// - /// Search for customers matching supplied query - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/customers/search")] - [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult Search(CustomersSearchParametersModel parameters) - { - if (parameters.Limit <= Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit" ,"Invalid limit parameter"); - } - - if (parameters.Page <= 0) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); - } - - var customersDto = _customerApiService.Search(parameters.Query, parameters.Order, parameters.Page, parameters.Limit); - - var customersRootObject = new CustomersRootObject() - { - Customers = customersDto - }; - - var json = JsonFieldsSerializer.Serialize(customersRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/customers")] - [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult CreateCustomer([ModelBinder(typeof(JsonModelBinder))] Delta customerDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - //If the validation has passed the customerDelta object won't be null for sure so we don't need to check for this. - - // Inserting the new customer - var newCustomer = _factory.Initialize(); - customerDelta.Merge(newCustomer); - - foreach (var address in customerDelta.Dto.Addresses) - { - // we need to explicitly set the date as if it is not specified - // it will default to 01/01/0001 which is not supported by SQL Server and throws and exception - if (address.CreatedOnUtc == null) - { - address.CreatedOnUtc = DateTime.UtcNow; - } - newCustomer.Addresses.Add(address.ToEntity()); - } - - CustomerService.InsertCustomer(newCustomer); - - InsertFirstAndLastNameGenericAttributes(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, newCustomer); - - if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) - && _languageService.GetLanguageById(languageId) != null) - { - _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); - } - - //password - if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) - { - AddPassword(customerDelta.Dto.Password, newCustomer); - } - - // We need to insert the entity first so we can have its id in order to map it to anything. - // TODO: Localization - // TODO: move this before inserting the customer. - if (customerDelta.Dto.RoleIds.Count > 0) - { - AddValidRoles(customerDelta, newCustomer); - CustomerService.UpdateCustomer(newCustomer); - } - - // Preparing the result dto of the new customer - // We do not prepare the shopping cart items because we have a separate endpoint for them. - var newCustomerDto = newCustomer.ToDto(); - - // This is needed because the entity framework won't populate the navigation properties automatically - // and the country will be left null. So we do it by hand here. - PopulateAddressCountryNames(newCustomerDto); - - // Set the fist and last name separately because they are not part of the customer entity, but are saved in the generic attributes. - newCustomerDto.FirstName = customerDelta.Dto.FirstName; - newCustomerDto.LastName = customerDelta.Dto.LastName; - - newCustomerDto.LanguageId = customerDelta.Dto.LanguageId; - - //activity log - CustomerActivityService.InsertActivity("AddNewCustomer", LocalizationService.GetResource("ActivityLog.AddNewCustomer"), newCustomer); - - var customersRootObject = new CustomersRootObject(); - - customersRootObject.Customers.Add(newCustomerDto); - - var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/customers/{id}")] - [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult UpdateCustomer([ModelBinder(typeof(JsonModelBinder))] Delta customerDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - // Updateting the customer - var currentCustomer = _customerApiService.GetCustomerEntityById(customerDelta.Dto.Id); - - if (currentCustomer == null) - { - return Error(HttpStatusCode.NotFound, "customer", "not found"); - } - - customerDelta.Merge(currentCustomer); - - if (customerDelta.Dto.RoleIds.Count > 0) - { - AddValidRoles(customerDelta, currentCustomer); - } - - if (customerDelta.Dto.Addresses.Count > 0) - { - var currentCustomerAddresses = currentCustomer.Addresses.ToDictionary(address => address.Id, address => address); - - foreach (var passedAddress in customerDelta.Dto.Addresses) - { - var addressEntity = passedAddress.ToEntity(); - - if (currentCustomerAddresses.ContainsKey(passedAddress.Id)) - { - _mappingHelper.Merge(passedAddress, currentCustomerAddresses[passedAddress.Id]); - } - else - { - currentCustomer.Addresses.Add(addressEntity); - } - } - } - - CustomerService.UpdateCustomer(currentCustomer); - - InsertFirstAndLastNameGenericAttributes(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, currentCustomer); - - - if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) - && _languageService.GetLanguageById(languageId) != null) - { - _genericAttributeService.SaveAttribute(currentCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); - } - - //password - if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) - { - AddPassword(customerDelta.Dto.Password, currentCustomer); - } - - // TODO: Localization - - // Preparing the result dto of the new customer - // We do not prepare the shopping cart items because we have a separate endpoint for them. - var updatedCustomer = currentCustomer.ToDto(); - - // This is needed because the entity framework won't populate the navigation properties automatically - // and the country name will be left empty because the mapping depends on the navigation property - // so we do it by hand here. - PopulateAddressCountryNames(updatedCustomer); - - // Set the fist and last name separately because they are not part of the customer entity, but are saved in the generic attributes. - var firstNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) - .FirstOrDefault(x => x.Key == "FirstName"); - - if (firstNameGenericAttribute != null) - { - updatedCustomer.FirstName = firstNameGenericAttribute.Value; - } - - var lastNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) - .FirstOrDefault(x => x.Key == "LastName"); - - if (lastNameGenericAttribute != null) - { - updatedCustomer.LastName = lastNameGenericAttribute.Value; - } - - var languageIdGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) - .FirstOrDefault(x => x.Key == "LanguageId"); - - if (languageIdGenericAttribute != null) - { - updatedCustomer.LanguageId = languageIdGenericAttribute.Value; - } - - //activity log - CustomerActivityService.InsertActivity("UpdateCustomer", LocalizationService.GetResource("ActivityLog.UpdateCustomer"), currentCustomer); - - var customersRootObject = new CustomersRootObject(); - - customersRootObject.Customers.Add(updatedCustomer); - - var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/customers/{id}")] - [GetRequestsErrorInterceptorActionFilter] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult DeleteCustomer(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var customer = _customerApiService.GetCustomerEntityById(id); - - if (customer == null) - { - return Error(HttpStatusCode.NotFound, "customer", "not found"); - } - - CustomerService.DeleteCustomer(customer); - - //remove newsletter subscription (if exists) - foreach (var store in StoreService.GetAllStores()) - { - var subscription = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmailAndStoreId(customer.Email, store.Id); - if (subscription != null) - _newsLetterSubscriptionService.DeleteNewsLetterSubscription(subscription); - } - - //activity log - CustomerActivityService.InsertActivity("DeleteCustomer", LocalizationService.GetResource("ActivityLog.DeleteCustomer"), customer); - - return new RawJsonActionResult("{}"); - } - - private void InsertFirstAndLastNameGenericAttributes(string firstName, string lastName, Customer newCustomer) - { - // we assume that if the first name is not sent then it will be null and in this case we don't want to update it - if (firstName != null) - { - _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.FirstNameAttribute, firstName); - } - - if (lastName != null) - { - _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.LastNameAttribute, lastName); - } - } - - private void AddValidRoles(Delta customerDelta, Customer currentCustomer) - { - var allCustomerRoles = CustomerService.GetAllCustomerRoles(true); - foreach (var customerRole in allCustomerRoles) - { - if (customerDelta.Dto.RoleIds.Contains(customerRole.Id)) - { - //new role - if (currentCustomer.CustomerCustomerRoleMappings.Count(mapping => mapping.CustomerRoleId == customerRole.Id) == 0) - currentCustomer.CustomerCustomerRoleMappings.Add(new CustomerCustomerRoleMapping { CustomerRole = customerRole }); - } - else - { - if (currentCustomer.CustomerCustomerRoleMappings.Count(mapping => mapping.CustomerRoleId == customerRole.Id) > 0) - { - currentCustomer.CustomerCustomerRoleMappings - .Remove(currentCustomer.CustomerCustomerRoleMappings.FirstOrDefault(mapping => mapping.CustomerRoleId == customerRole.Id)); - } - } - } - } - - private void PopulateAddressCountryNames(CustomerDto newCustomerDto) - { - foreach (var address in newCustomerDto.Addresses) - { - SetCountryName(address); - } - - if (newCustomerDto.BillingAddress != null) - { - SetCountryName(newCustomerDto.BillingAddress); - } - - if (newCustomerDto.ShippingAddress != null) - { - SetCountryName(newCustomerDto.ShippingAddress); - } - } - - private void SetCountryName(AddressDto address) - { - if (string.IsNullOrEmpty(address.CountryName) && address.CountryId.HasValue) - { - var country = _countryService.GetCountryById(address.CountryId.Value); - address.CountryName = country.Name; - } - } - - private void AddPassword(string newPassword, Customer customer) - { - // TODO: call this method before inserting the customer. - var customerPassword = new CustomerPassword - { - Customer = customer, - PasswordFormat = CustomerSettings.DefaultPasswordFormat, - CreatedOnUtc = DateTime.UtcNow - }; - - switch (CustomerSettings.DefaultPasswordFormat) - { - case PasswordFormat.Clear: - { - customerPassword.Password = newPassword; - } - break; - case PasswordFormat.Encrypted: - { - customerPassword.Password = _encryptionService.EncryptText(newPassword); - } - break; - case PasswordFormat.Hashed: - { - var saltKey = _encryptionService.CreateSaltKey(5); - customerPassword.PasswordSalt = saltKey; - customerPassword.Password = _encryptionService.CreatePasswordHash(newPassword, saltKey, CustomerSettings.HashedPasswordFormat); - } - break; - } - - CustomerService.InsertCustomerPassword(customerPassword); - - // TODO: remove this. - CustomerService.UpdateCustomer(customer); - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Customers; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.CustomersParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Common; +using Nop.Services.Customers; +using Nop.Services.Directory; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Messages; +using Nop.Services.Plugins; +using Nop.Services.Security; +using Nop.Services.Stores; +using System; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class CustomersController : BaseApiController + { + private readonly ICustomerApiService _customerApiService; + private readonly ICustomerRolesHelper _customerRolesHelper; + private readonly IGenericAttributeService _genericAttributeService; + private readonly IEncryptionService _encryptionService; + private readonly ICountryService _countryService; + private readonly IMappingHelper _mappingHelper; + private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; + private readonly ILanguageService _languageService; + private readonly IFactory _factory; + private readonly IDTOHelper _dtoHelper; + + // We resolve the customer settings this way because of the tests. + // The auto mocking does not support concreate types as dependencies. It supports only interfaces. + private CustomerSettings _customerSettings; + + private CustomerSettings CustomerSettings + { + get + { + if (_customerSettings == null) + { + _customerSettings = EngineContext.Current.Resolve(); + } + + return _customerSettings; + } + } + + public CustomersController( + ICustomerApiService customerApiService, + IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + ICustomerRolesHelper customerRolesHelper, + IGenericAttributeService genericAttributeService, + IEncryptionService encryptionService, + IFactory factory, + ICountryService countryService, + IMappingHelper mappingHelper, + IPluginService pluginService, + INewsLetterSubscriptionService newsLetterSubscriptionService, + IPictureService pictureService, + ILanguageService languageService, + IDTOHelper dtoHelper) : + base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _customerApiService = customerApiService; + _factory = factory; + _countryService = countryService; + _mappingHelper = mappingHelper; + _newsLetterSubscriptionService = newsLetterSubscriptionService; + _languageService = languageService; + _encryptionService = encryptionService; + _genericAttributeService = genericAttributeService; + _customerRolesHelper = customerRolesHelper; + _dtoHelper = dtoHelper; + } + + /// + /// Retrieve all customers of a shop + /// + /// OK + /// Bad request + /// Unauthorized + [HttpGet] + [Route("/api/customers")] + [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCustomers(CustomersParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid request parameters"); + } + + try + { + var allCustomers = _customerApiService.GetCustomersDtos(parameters.CreatedAtMin, + parameters.CreatedAtMax, + parameters.Limit, + parameters.Page, + parameters.SinceId); + + var customersRootObject = new CustomersRootObject() + { + Customers = allCustomers + }; + + var json = JsonFieldsSerializer.Serialize(customersRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + catch (Exception ex) + { + throw; + } + + } + + /// + /// Retrieve customer by spcified id + /// + /// Id of the customer + /// Fields from the customer you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/customers/{id}")] + [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCustomerById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var customer = _customerApiService.GetCustomerById(id); + + if (customer == null) + { + return Error(HttpStatusCode.NotFound, "customer", "not found"); + } + + var customersRootObject = new CustomersRootObject(); + customersRootObject.Customers.Add(customer); + + var json = JsonFieldsSerializer.Serialize(customersRootObject, fields); + + return new RawJsonActionResult(json); + } + + + /// + /// Get a count of all customers + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/customers/count")] + [ProducesResponseType(typeof(CustomersCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + public IActionResult GetCustomersCount() + { + var allCustomersCount = _customerApiService.GetCustomersCount(); + + var customersCountRootObject = new CustomersCountRootObject() + { + Count = allCustomersCount + }; + + return Ok(customersCountRootObject); + } + + /// + /// Search for customers matching supplied query + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/customers/search")] + [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult Search(CustomersSearchParametersModel parameters) + { + if (parameters.Limit <= Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit" ,"Invalid limit parameter"); + } + + if (parameters.Page <= 0) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); + } + + var customersDto = _customerApiService.Search(parameters.Query, parameters.Order, parameters.Page, parameters.Limit); + + var customersRootObject = new CustomersRootObject() + { + Customers = customersDto + }; + + var json = JsonFieldsSerializer.Serialize(customersRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/customers")] + [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult CreateCustomer([ModelBinder(typeof(JsonModelBinder))] Delta customerDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var customer = CustomerService.GetCustomerByEmail(customerDelta.Dto.Email); + if (customer != null && !customer.Deleted) + return Error(HttpStatusCode.Conflict, nameof(Customer.Email), "Email is already registered"); + + //If the validation has passed the customerDelta object won't be null for sure so we don't need to check for this. + + // Inserting the new customer + var newCustomer = _factory.Initialize(); + customerDelta.Merge(newCustomer); + + foreach (var address in customerDelta.Dto.Addresses) + { + // we need to explicitly set the date as if it is not specified + // it will default to 01/01/0001 which is not supported by SQL Server and throws and exception + if (address.CreatedOnUtc == null) + { + address.CreatedOnUtc = DateTime.UtcNow; + } + + CustomerService.InsertCustomerAddress(newCustomer, address.ToEntity()); + } + + CustomerService.InsertCustomer(newCustomer); + + InsertFirstAndLastNameGenericAttributes(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, newCustomer); + + if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) + && _languageService.GetLanguageById(languageId) != null) + { + _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); + } + + //password + if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) + { + AddPassword(customerDelta.Dto.Password, newCustomer); + } + + // We need to insert the entity first so we can have its id in order to map it to anything. + // TODO: Localization + // TODO: move this before inserting the customer. + if (customerDelta.Dto.RoleIds.Count > 0) + { + AddValidRoles(customerDelta, newCustomer); + } + + // Preparing the result dto of the new customer + // We do not prepare the shopping cart items because we have a separate endpoint for them. + var newCustomerDto = _dtoHelper.PrepareCustomerDTO(newCustomer); + + // This is needed because the entity framework won't populate the navigation properties automatically + // and the country will be left null. So we do it by hand here. + PopulateAddressCountryNames(newCustomerDto); + + // Set the fist and last name separately because they are not part of the customer entity, but are saved in the generic attributes. + newCustomerDto.FirstName = customerDelta.Dto.FirstName; + newCustomerDto.LastName = customerDelta.Dto.LastName; + + newCustomerDto.LanguageId = customerDelta.Dto.LanguageId; + + //activity log + CustomerActivityService.InsertActivity("AddNewCustomer", LocalizationService.GetResource("ActivityLog.AddNewCustomer"), newCustomer); + + var customersRootObject = new CustomersRootObject(); + + customersRootObject.Customers.Add(newCustomerDto); + + var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/customers/{id}")] + [ProducesResponseType(typeof(CustomersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult UpdateCustomer([ModelBinder(typeof(JsonModelBinder))] Delta customerDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + // Updateting the customer + var currentCustomer = _customerApiService.GetCustomerEntityById(customerDelta.Dto.Id); + + if (currentCustomer == null) + { + return Error(HttpStatusCode.NotFound, "customer", "not found"); + } + + customerDelta.Merge(currentCustomer); + + if (customerDelta.Dto.RoleIds.Count > 0) + { + AddValidRoles(customerDelta, currentCustomer); + } + + if (customerDelta.Dto.Addresses.Count > 0) + { + var currentCustomerAddresses = CustomerService.GetAddressesByCustomerId(currentCustomer.Id).ToDictionary(address => address.Id, address => address); + + foreach (var passedAddress in customerDelta.Dto.Addresses) + { + var addressEntity = passedAddress.ToEntity(); + + if (currentCustomerAddresses.ContainsKey(passedAddress.Id)) + { + _mappingHelper.Merge(passedAddress, currentCustomerAddresses[passedAddress.Id]); + } + else + { + CustomerService.InsertCustomerAddress(currentCustomer, addressEntity); + } + } + } + + CustomerService.UpdateCustomer(currentCustomer); + + InsertFirstAndLastNameGenericAttributes(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, currentCustomer); + + + if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) + && _languageService.GetLanguageById(languageId) != null) + { + _genericAttributeService.SaveAttribute(currentCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); + } + + //password + if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) + { + AddPassword(customerDelta.Dto.Password, currentCustomer); + } + + // TODO: Localization + + // Preparing the result dto of the new customer + // We do not prepare the shopping cart items because we have a separate endpoint for them. + var updatedCustomer = _dtoHelper.PrepareCustomerDTO(currentCustomer); + + // This is needed because the entity framework won't populate the navigation properties automatically + // and the country name will be left empty because the mapping depends on the navigation property + // so we do it by hand here. + PopulateAddressCountryNames(updatedCustomer); + + // Set the fist and last name separately because they are not part of the customer entity, but are saved in the generic attributes. + var firstNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) + .FirstOrDefault(x => x.Key == "FirstName"); + + if (firstNameGenericAttribute != null) + { + updatedCustomer.FirstName = firstNameGenericAttribute.Value; + } + + var lastNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) + .FirstOrDefault(x => x.Key == "LastName"); + + if (lastNameGenericAttribute != null) + { + updatedCustomer.LastName = lastNameGenericAttribute.Value; + } + + var languageIdGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) + .FirstOrDefault(x => x.Key == "LanguageId"); + + if (languageIdGenericAttribute != null) + { + updatedCustomer.LanguageId = languageIdGenericAttribute.Value; + } + + //activity log + CustomerActivityService.InsertActivity("UpdateCustomer", LocalizationService.GetResource("ActivityLog.UpdateCustomer"), currentCustomer); + + var customersRootObject = new CustomersRootObject(); + + customersRootObject.Customers.Add(updatedCustomer); + + var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/customers/{id}")] + [GetRequestsErrorInterceptorActionFilter] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult DeleteCustomer(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var customer = _customerApiService.GetCustomerEntityById(id); + + if (customer == null) + { + return Error(HttpStatusCode.NotFound, "customer", "not found"); + } + + CustomerService.DeleteCustomer(customer); + + //remove newsletter subscription (if exists) + foreach (var store in StoreService.GetAllStores()) + { + var subscription = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmailAndStoreId(customer.Email, store.Id); + if (subscription != null) + _newsLetterSubscriptionService.DeleteNewsLetterSubscription(subscription); + } + + //activity log + CustomerActivityService.InsertActivity("DeleteCustomer", LocalizationService.GetResource("ActivityLog.DeleteCustomer"), customer); + + return new RawJsonActionResult("{}"); + } + + private void InsertFirstAndLastNameGenericAttributes(string firstName, string lastName, Customer newCustomer) + { + // we assume that if the first name is not sent then it will be null and in this case we don't want to update it + if (firstName != null) + { + _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.FirstNameAttribute, firstName); + } + + if (lastName != null) + { + _genericAttributeService.SaveAttribute(newCustomer, NopCustomerDefaults.LastNameAttribute, lastName); + } + } + + private void AddValidRoles(Delta customerDelta, Customer currentCustomer) + { + var allCustomerRoles = CustomerService.GetAllCustomerRoles(true); + foreach (var customerRole in allCustomerRoles) + { + if (customerDelta.Dto.RoleIds.Contains(customerRole.Id)) + { + //new role + if (!CustomerService.IsInCustomerRole(currentCustomer, customerRole.SystemName)) + { + CustomerService.AddCustomerRoleMapping(new CustomerCustomerRoleMapping() + { + CustomerId = currentCustomer.Id, + CustomerRoleId = customerRole.Id + }); + } + } + else + { + if (CustomerService.IsInCustomerRole(currentCustomer, customerRole.SystemName)) + { + CustomerService.RemoveCustomerRoleMapping(currentCustomer, customerRole); + } + } + } + } + + private void PopulateAddressCountryNames(CustomerDto newCustomerDto) + { + foreach (var address in newCustomerDto.Addresses) + { + SetCountryName(address); + } + + if (newCustomerDto.BillingAddress != null) + { + SetCountryName(newCustomerDto.BillingAddress); + } + + if (newCustomerDto.ShippingAddress != null) + { + SetCountryName(newCustomerDto.ShippingAddress); + } + } + + private void SetCountryName(AddressDto address) + { + if (string.IsNullOrEmpty(address.CountryName) && address.CountryId.HasValue) + { + var country = _countryService.GetCountryById(address.CountryId.Value); + address.CountryName = country.Name; + } + } + + private void AddPassword(string newPassword, Customer customer) + { + // TODO: call this method before inserting the customer. + var customerPassword = new CustomerPassword + { + CustomerId = customer.Id, + PasswordFormat = CustomerSettings.DefaultPasswordFormat, + CreatedOnUtc = DateTime.UtcNow + }; + + switch (CustomerSettings.DefaultPasswordFormat) + { + case PasswordFormat.Clear: + { + customerPassword.Password = newPassword; + } + break; + case PasswordFormat.Encrypted: + { + customerPassword.Password = _encryptionService.EncryptText(newPassword); + } + break; + case PasswordFormat.Hashed: + { + var saltKey = _encryptionService.CreateSaltKey(5); + customerPassword.PasswordSalt = saltKey; + customerPassword.Password = _encryptionService.CreatePasswordHash(newPassword, saltKey, CustomerSettings.HashedPasswordFormat); + } + break; + } + + CustomerService.InsertCustomerPassword(customerPassword); + + CustomerService.UpdateCustomer(customer); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/LanguagesController.cs b/Controllers/LanguagesController.cs similarity index 83% rename from Nop.Plugin.Api/Controllers/LanguagesController.cs rename to Controllers/LanguagesController.cs index 98f6bd9..1ab26be 100644 --- a/Nop.Plugin.Api/Controllers/LanguagesController.cs +++ b/Controllers/LanguagesController.cs @@ -1,82 +1,80 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Controllers -{ - using System.Net; - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class LanguagesController : BaseApiController - { - private ILanguageService _languageService; - private readonly IDTOHelper _dtoHelper; - - public LanguagesController(IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService, - ILanguageService languageService, - IDTOHelper dtoHelper) - : base(jsonFieldsSerializer, - aclService, - customerService, - storeMappingService, - storeService, - discountService, - customerActivityService, - localizationService, - pictureService) - { - _languageService = languageService; - _dtoHelper = dtoHelper; - } - - /// - /// Retrieve all languages - /// - /// Fields from the language you want your json to contain - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/languages")] - [ProducesResponseType(typeof(LanguagesRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetAllLanguages(string fields = "") - { - var allLanguages = _languageService.GetAllLanguages(); - - IList languagesAsDto = allLanguages.Select(language => _dtoHelper.PrepateLanguageDto(language)).ToList(); - - var languagesRootObject = new LanguagesRootObject() - { - Languages = languagesAsDto - }; - - var json = JsonFieldsSerializer.Serialize(languagesRootObject, fields); - - return new RawJsonActionResult(json); - } - } -} +using Microsoft.AspNetCore.Mvc; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Languages; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Nop.Plugin.Api.Controllers +{ + + public class LanguagesController : BaseApiController + { + private ILanguageService _languageService; + private readonly IDTOHelper _dtoHelper; + + public LanguagesController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService, + ILanguageService languageService, + IDTOHelper dtoHelper) + : base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _languageService = languageService; + _dtoHelper = dtoHelper; + } + + /// + /// Retrieve all languages + /// + /// Fields from the language you want your json to contain + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/languages")] + [ProducesResponseType(typeof(LanguagesRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetAllLanguages(string fields = "") + { + var allLanguages = _languageService.GetAllLanguages(); + + IList languagesAsDto = allLanguages.Select(language => _dtoHelper.PrepareLanguageDto(language)).ToList(); + + var languagesRootObject = new LanguagesRootObject() + { + Languages = languagesAsDto + }; + + var json = JsonFieldsSerializer.Serialize(languagesRootObject, fields); + + return new RawJsonActionResult(json); + } + } +} diff --git a/Nop.Plugin.Api/Controllers/ManufacturersController.cs b/Controllers/ManufacturersController.cs similarity index 90% rename from Nop.Plugin.Api/Controllers/ManufacturersController.cs rename to Controllers/ManufacturersController.cs index d552b00..4ea7d9e 100644 --- a/Nop.Plugin.Api/Controllers/ManufacturersController.cs +++ b/Controllers/ManufacturersController.cs @@ -1,14 +1,12 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Discounts; using Nop.Core.Domain.Media; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Manufacturers; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Manufacturers; using Nop.Plugin.Api.Factories; using Nop.Plugin.Api.Helpers; using Nop.Plugin.Api.JSON.ActionResults; @@ -29,32 +27,32 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Controllers { - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class ManufacturersController : BaseApiController { private readonly IFactory _factory; private readonly IDTOHelper _dtoHelper; private readonly IManufacturerService _manufacturerService; private readonly IManufacturerApiService _manufacturerApiService; - private readonly IUrlRecordService _urlRecordService; + private readonly IUrlRecordService _urlRecordService; - public ManufacturersController(IJsonFieldsSerializer jsonFieldsSerializer, + public ManufacturersController(IJsonFieldsSerializer jsonFieldsSerializer, IAclService aclService, - ICustomerService customerService, + ICustomerService customerService, IStoreMappingService storeMappingService, IStoreService storeService, IDiscountService discountService, ICustomerActivityService customerActivityService, ILocalizationService localizationService, - IPictureService pictureService, - IDTOHelper dtoHelper, + IPictureService pictureService, + IDTOHelper dtoHelper, IManufacturerService manufacturerService, IManufacturerApiService manufacturerApiService, IUrlRecordService urlRecordService, - IFactory factory) + IFactory factory) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) { _dtoHelper = dtoHelper; @@ -204,7 +202,6 @@ public IActionResult CreateManufacturer([ModelBinder(typeof(JsonModelBinder passedDiscountIds) { if (passedDiscountIds == null) + { return; + } var allDiscounts = DiscountService.GetAllDiscounts(DiscountType.AssignedToManufacturers, showHidden: true); foreach (var discount in allDiscounts) { + var appliedDiscounts = DiscountService.GetAppliedDiscounts(manufacturer); if (passedDiscountIds.Contains(discount.Id)) { //new discount - if (manufacturer.AppliedDiscounts.Count(d => d.Id == discount.Id) == 0) - manufacturer.AppliedDiscounts.Add(discount); + if (appliedDiscounts.Count(d => d.Id == discount.Id) == 0) + { + _manufacturerService.InsertDiscountManufacturerMapping( + new DiscountManufacturerMapping + { + DiscountId = discount.Id, + EntityId = manufacturer.Id + }); + } } else { //remove discount - if (manufacturer.AppliedDiscounts.Count(d => d.Id == discount.Id) > 0) - manufacturer.AppliedDiscounts.Remove(discount); + if (appliedDiscounts.Count(d => d.Id == discount.Id) > 0) + { + _manufacturerService.DeleteDiscountManufacturerMapping( + new DiscountManufacturerMapping + { + DiscountId = discount.Id, + EntityId = manufacturer.Id + }); + + } } } _manufacturerService.UpdateManufacturer(manufacturer); } } -} +} \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/NewsLetterSubscriptionController.cs b/Controllers/NewsLetterSubscriptionController.cs similarity index 91% rename from Nop.Plugin.Api/Controllers/NewsLetterSubscriptionController.cs rename to Controllers/NewsLetterSubscriptionController.cs index 14fff2f..74b32af 100644 --- a/Nop.Plugin.Api/Controllers/NewsLetterSubscriptionController.cs +++ b/Controllers/NewsLetterSubscriptionController.cs @@ -1,122 +1,120 @@ -using System.Linq; -using System.Net; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; -using Nop.Core; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.JSON.Serializers; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.Models.CustomersParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Messages; -using Nop.Services.Security; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Controllers -{ - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class NewsLetterSubscriptionController : BaseApiController - { - private readonly INewsLetterSubscriptionApiService _newsLetterSubscriptionApiService; - private readonly IStoreContext _storeContext; - private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; - - public NewsLetterSubscriptionController(IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService, - INewsLetterSubscriptionApiService newsLetterSubscriptionApiService, - IStoreContext storeContext, - INewsLetterSubscriptionService newsLetterSubscriptionService) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) - { - _newsLetterSubscriptionApiService = newsLetterSubscriptionApiService; - _storeContext = storeContext; - _newsLetterSubscriptionService = newsLetterSubscriptionService; - } - - /// - /// Receive a list of all NewsLetters - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/news_letter_subscriptions")] - [ProducesResponseType(typeof(NewsLetterSubscriptionsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetNewsLetterSubscriptions(NewsLetterSubscriptionsParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); - } - - var newsLetterSubscriptions = _newsLetterSubscriptionApiService.GetNewsLetterSubscriptions(parameters.CreatedAtMin, parameters.CreatedAtMax, - parameters.Limit, parameters.Page, parameters.SinceId, - parameters.OnlyActive); - - var newsLetterSubscriptionsDtos = newsLetterSubscriptions.Select(nls => nls.ToDto()).ToList(); - - var newsLetterSubscriptionsRootObject = new NewsLetterSubscriptionsRootObject() - { - NewsLetterSubscriptions = newsLetterSubscriptionsDtos - }; - - var json = JsonFieldsSerializer.Serialize(newsLetterSubscriptionsRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Deactivate a NewsLetter subscriber by email - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpPost] - [Route("/api/news_letter_subscriptions/{email}/deactivate")] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - public IActionResult DeactivateNewsLetterSubscription(string email) - { - if (string.IsNullOrEmpty(email)) - { - return Error(HttpStatusCode.BadRequest, "The email parameter could not be empty."); - } - - var existingSubscription = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmailAndStoreId(email, _storeContext.CurrentStore.Id); - - if (existingSubscription == null) - { - return Error(HttpStatusCode.BadRequest, "There is no news letter subscription with the specified email."); - } - - existingSubscription.Active = false; - - _newsLetterSubscriptionService.UpdateNewsLetterSubscription(existingSubscription); - - return Ok(); - } - } -} +using Microsoft.AspNetCore.Mvc; +using Nop.Core; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Plugin.Api.Models.CustomersParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Messages; +using Nop.Services.Security; +using Nop.Services.Stores; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class NewsLetterSubscriptionController : BaseApiController + { + private readonly INewsLetterSubscriptionApiService _newsLetterSubscriptionApiService; + private readonly IStoreContext _storeContext; + private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; + + public NewsLetterSubscriptionController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService, + INewsLetterSubscriptionApiService newsLetterSubscriptionApiService, + IStoreContext storeContext, + INewsLetterSubscriptionService newsLetterSubscriptionService) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) + { + _newsLetterSubscriptionApiService = newsLetterSubscriptionApiService; + _storeContext = storeContext; + _newsLetterSubscriptionService = newsLetterSubscriptionService; + } + + /// + /// Receive a list of all NewsLetters + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/news_letter_subscriptions")] + [ProducesResponseType(typeof(NewsLetterSubscriptionsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetNewsLetterSubscriptions(NewsLetterSubscriptionsParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); + } + + var newsLetterSubscriptions = _newsLetterSubscriptionApiService.GetNewsLetterSubscriptions(parameters.CreatedAtMin, parameters.CreatedAtMax, + parameters.Limit, parameters.Page, parameters.SinceId, + parameters.OnlyActive); + + var newsLetterSubscriptionsDtos = newsLetterSubscriptions.Select(nls => nls.ToDto()).ToList(); + + var newsLetterSubscriptionsRootObject = new NewsLetterSubscriptionsRootObject() + { + NewsLetterSubscriptions = newsLetterSubscriptionsDtos + }; + + var json = JsonFieldsSerializer.Serialize(newsLetterSubscriptionsRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Deactivate a NewsLetter subscriber by email + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/api/news_letter_subscriptions/{email}/deactivate")] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult DeactivateNewsLetterSubscription(string email) + { + if (string.IsNullOrEmpty(email)) + { + return Error(HttpStatusCode.BadRequest, "The email parameter could not be empty."); + } + + var existingSubscription = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmailAndStoreId(email, _storeContext.CurrentStore.Id); + + if (existingSubscription == null) + { + return Error(HttpStatusCode.BadRequest, "There is no news letter subscription with the specified email."); + } + + existingSubscription.Active = false; + + _newsLetterSubscriptionService.UpdateNewsLetterSubscription(existingSubscription); + + return Ok(); + } + } +} diff --git a/Nop.Plugin.Api/Controllers/OrderItemsController.cs b/Controllers/OrderItemsController.cs similarity index 88% rename from Nop.Plugin.Api/Controllers/OrderItemsController.cs rename to Controllers/OrderItemsController.cs index e4b42b4..1874f03 100644 --- a/Nop.Plugin.Api/Controllers/OrderItemsController.cs +++ b/Controllers/OrderItemsController.cs @@ -1,400 +1,398 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.JSON.Serializers; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.OrderItemsParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Orders; -using Nop.Services.Security; -using Nop.Services.Stores; -using Nop.Services.Tax; - -namespace Nop.Plugin.Api.Controllers -{ - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, - AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class OrderItemsController : BaseApiController - { - private readonly IDTOHelper _dtoHelper; - private readonly IOrderApiService _orderApiService; - private readonly IOrderItemApiService _orderItemApiService; - private readonly IOrderService _orderService; - private readonly IPriceCalculationService _priceCalculationService; - private readonly IProductApiService _productApiService; - private readonly ITaxService _taxService; - - public OrderItemsController(IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IOrderItemApiService orderItemApiService, - IOrderApiService orderApiService, - IOrderService orderService, - IProductApiService productApiService, - IPriceCalculationService priceCalculationService, - ITaxService taxService, - IPictureService pictureService, IDTOHelper dtoHelper) - : base(jsonFieldsSerializer, - aclService, - customerService, - storeMappingService, - storeService, - discountService, - customerActivityService, - localizationService, - pictureService) - { - _orderItemApiService = orderItemApiService; - _orderApiService = orderApiService; - _orderService = orderService; - _productApiService = productApiService; - _priceCalculationService = priceCalculationService; - _taxService = taxService; - _dtoHelper = dtoHelper; - } - - [HttpGet] - [Route("/api/orders/{orderId}/items")] - [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrderItems(int orderId, OrderItemsParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid request parameters"); - } - - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var allOrderItemsForOrder = - _orderItemApiService.GetOrderItemsForOrder(order, parameters.Limit, parameters.Page, - parameters.SinceId); - - var orderItemsRootObject = new OrderItemsRootObject - { - OrderItems = allOrderItemsForOrder.Select(item => _dtoHelper.PrepareOrderItemDTO(item)).ToList() - }; - - var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - [HttpGet] - [Route("/api/orders/{orderId}/items/count")] - [ProducesResponseType(typeof(OrderItemsCountRootObject), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrderItemsCount(int orderId) - { - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var orderItemsCountForOrder = _orderItemApiService.GetOrderItemsCount(order); - - var orderItemsCountRootObject = new OrderItemsCountRootObject - { - Count = orderItemsCountForOrder - }; - - return Ok(orderItemsCountRootObject); - } - - [HttpGet] - [Route("/api/orders/{orderId}/items/{orderItemId}")] - [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrderItemByIdForOrder(int orderId, int orderItemId, string fields = "") - { - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var orderItem = _orderService.GetOrderItemById(orderItemId); - - if (orderItem == null) - { - return Error(HttpStatusCode.NotFound, "order_item", "not found"); - } - - var orderItemDtos = new List {_dtoHelper.PrepareOrderItemDTO(orderItem)}; - - var orderItemsRootObject = new OrderItemsRootObject - { - OrderItems = orderItemDtos - }; - - var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/orders/{orderId}/items")] - [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - public IActionResult CreateOrderItem(int orderId, - [ModelBinder(typeof(JsonModelBinder))] - Delta orderItemDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var product = GetProduct(orderItemDelta.Dto.ProductId); - - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product", "not found"); - } - - if (product.IsRental) - { - if (orderItemDelta.Dto.RentalStartDateUtc == null) - { - return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", "required"); - } - - if (orderItemDelta.Dto.RentalEndDateUtc == null) - { - return Error(HttpStatusCode.BadRequest, "rental_end_date_utc", "required"); - } - - if (orderItemDelta.Dto.RentalStartDateUtc > orderItemDelta.Dto.RentalEndDateUtc) - { - return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", - "should be before rental_end_date_utc"); - } - - if (orderItemDelta.Dto.RentalStartDateUtc < DateTime.UtcNow) - { - return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", "should be a future date"); - } - } - - var newOrderItem = PrepareDefaultOrderItemFromProduct(order, product); - orderItemDelta.Merge(newOrderItem); - - order.OrderItems.Add(newOrderItem); - - _orderService.UpdateOrder(order); - - CustomerActivityService.InsertActivity("AddNewOrderItem", - LocalizationService.GetResource("ActivityLog.AddNewOrderItem"), newOrderItem); - - var orderItemsRootObject = new OrderItemsRootObject(); - - orderItemsRootObject.OrderItems.Add(newOrderItem.ToDto()); - - var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/orders/{orderId}/items/{orderItemId}")] - [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - public IActionResult UpdateOrderItem(int orderId, int orderItemId, - [ModelBinder(typeof(JsonModelBinder))] - Delta orderItemDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var orderItemToUpdate = _orderService.GetOrderItemById(orderItemId); - - if (orderItemToUpdate == null) - { - return Error(HttpStatusCode.NotFound, "order_item", "not found"); - } - - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - // This is needed because those fields shouldn't be updatable. That is why we save them and after the merge set them back. - int? productId = orderItemToUpdate.ProductId; - var rentalStartDate = orderItemToUpdate.RentalStartDateUtc; - var rentalEndDate = orderItemToUpdate.RentalEndDateUtc; - - orderItemDelta.Merge(orderItemToUpdate); - - orderItemToUpdate.ProductId = (int) productId; - orderItemToUpdate.RentalStartDateUtc = rentalStartDate; - orderItemToUpdate.RentalEndDateUtc = rentalEndDate; - - _orderService.UpdateOrder(order); - - CustomerActivityService.InsertActivity("UpdateOrderItem", - LocalizationService.GetResource("ActivityLog.UpdateOrderItem"), orderItemToUpdate); - - var orderItemsRootObject = new OrderItemsRootObject(); - - orderItemsRootObject.OrderItems.Add(orderItemToUpdate.ToDto()); - - var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/orders/{orderId}/items/{orderItemId}")] - [ProducesResponseType(typeof(void), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteOrderItemById(int orderId, int orderItemId) - { - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var orderItem = _orderService.GetOrderItemById(orderItemId); - _orderService.DeleteOrderItem(orderItem); - - return new RawJsonActionResult("{}"); - } - - [HttpDelete] - [Route("/api/orders/{orderId}/items")] - [ProducesResponseType(typeof(void), (int) HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteAllOrderItemsForOrder(int orderId) - { - var order = _orderApiService.GetOrderById(orderId); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var orderItemsList = order.OrderItems.ToList(); - - foreach (var t in orderItemsList) - { - _orderService.DeleteOrderItem(t); - } - - return new RawJsonActionResult("{}"); - } - - private Product GetProduct(int? productId) - { - Product product = null; - - if (productId.HasValue) - { - var id = productId.Value; - - product = _productApiService.GetProductById(id); - } - - return product; - } - - private OrderItem PrepareDefaultOrderItemFromProduct(Order order, Product product) - { - var presetQty = 1; - var presetPrice = - _priceCalculationService.GetFinalPrice(product, order.Customer, decimal.Zero, true, presetQty); - - var presetPriceInclTax = - _taxService.GetProductPrice(product, presetPrice, true, order.Customer, out _); - var presetPriceExclTax = - _taxService.GetProductPrice(product, presetPrice, false, order.Customer, out _); - - var orderItem = new OrderItem - { - OrderItemGuid = new Guid(), - UnitPriceExclTax = presetPriceExclTax, - UnitPriceInclTax = presetPriceInclTax, - PriceInclTax = presetPriceInclTax, - PriceExclTax = presetPriceExclTax, - OriginalProductCost = _priceCalculationService.GetProductCost(product, null), - Quantity = presetQty, - Product = product, - Order = order - }; - - return orderItem; - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Orders; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.OrderItemsParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Orders; +using Nop.Services.Security; +using Nop.Services.Stores; +using Nop.Services.Tax; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class OrderItemsController : BaseApiController + { + private readonly IDTOHelper _dtoHelper; + private readonly IOrderApiService _orderApiService; + private readonly IOrderItemApiService _orderItemApiService; + private readonly IOrderService _orderService; + private readonly IPriceCalculationService _priceCalculationService; + private readonly IProductApiService _productApiService; + private readonly ITaxService _taxService; + + public OrderItemsController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IOrderItemApiService orderItemApiService, + IOrderApiService orderApiService, + IOrderService orderService, + IProductApiService productApiService, + IPriceCalculationService priceCalculationService, + ITaxService taxService, + IPictureService pictureService, IDTOHelper dtoHelper) + : base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _orderItemApiService = orderItemApiService; + _orderApiService = orderApiService; + _orderService = orderService; + _productApiService = productApiService; + _priceCalculationService = priceCalculationService; + _taxService = taxService; + _dtoHelper = dtoHelper; + } + + [HttpGet] + [Route("/api/orders/{orderId}/items")] + [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrderItems(int orderId, OrderItemsParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "Invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid request parameters"); + } + + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var allOrderItemsForOrder = + _orderItemApiService.GetOrderItemsForOrder(order, parameters.Limit, parameters.Page, + parameters.SinceId); + + var orderItemsRootObject = new OrderItemsRootObject + { + OrderItems = allOrderItemsForOrder.Select(item => _dtoHelper.PrepareOrderItemDTO(item)).ToList() + }; + + var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + [HttpGet] + [Route("/api/orders/{orderId}/items/count")] + [ProducesResponseType(typeof(OrderItemsCountRootObject), (int) HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrderItemsCount(int orderId) + { + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var orderItemsCountForOrder = _orderItemApiService.GetOrderItemsCount(order); + + var orderItemsCountRootObject = new OrderItemsCountRootObject + { + Count = orderItemsCountForOrder + }; + + return Ok(orderItemsCountRootObject); + } + + [HttpGet] + [Route("/api/orders/{orderId}/items/{orderItemId}")] + [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrderItemByIdForOrder(int orderId, int orderItemId, string fields = "") + { + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var orderItem = _orderService.GetOrderItemById(orderItemId); + + if (orderItem == null) + { + return Error(HttpStatusCode.NotFound, "order_item", "not found"); + } + + var orderItemDtos = new List {_dtoHelper.PrepareOrderItemDTO(orderItem)}; + + var orderItemsRootObject = new OrderItemsRootObject + { + OrderItems = orderItemDtos + }; + + var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/orders/{orderId}/items")] + [ProducesResponseType(typeof(OrderItemsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + public IActionResult CreateOrderItem( + int orderId, + [ModelBinder(typeof(JsonModelBinder))] + Delta orderItemDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var product = GetProduct(orderItemDelta.Dto.ProductId); + + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product", "not found"); + } + + if (product.IsRental) + { + if (orderItemDelta.Dto.RentalStartDateUtc == null) + { + return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", "required"); + } + + if (orderItemDelta.Dto.RentalEndDateUtc == null) + { + return Error(HttpStatusCode.BadRequest, "rental_end_date_utc", "required"); + } + + if (orderItemDelta.Dto.RentalStartDateUtc > orderItemDelta.Dto.RentalEndDateUtc) + { + return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", + "should be before rental_end_date_utc"); + } + + if (orderItemDelta.Dto.RentalStartDateUtc < DateTime.UtcNow) + { + return Error(HttpStatusCode.BadRequest, "rental_start_date_utc", "should be a future date"); + } + } + + var newOrderItem = PrepareDefaultOrderItemFromProduct(order, product); + orderItemDelta.Merge(newOrderItem); + _orderService.InsertOrderItem(newOrderItem); + + _orderService.UpdateOrder(order); + + CustomerActivityService.InsertActivity("AddNewOrderItem", + LocalizationService.GetResource("ActivityLog.AddNewOrderItem"), newOrderItem); + + var orderItemsRootObject = new OrderItemsRootObject(); + + orderItemsRootObject.OrderItems.Add(newOrderItem.ToDto()); + + var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/orders/{orderId}/items/{orderItemId}")] + [ProducesResponseType(typeof(OrderItemsRootObject), (int) HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] + public IActionResult UpdateOrderItem(int orderId, int orderItemId, + [ModelBinder(typeof(JsonModelBinder))] + Delta orderItemDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var orderItemToUpdate = _orderService.GetOrderItemById(orderItemId); + + if (orderItemToUpdate == null) + { + return Error(HttpStatusCode.NotFound, "order_item", "not found"); + } + + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + // This is needed because those fields shouldn't be updatable. That is why we save them and after the merge set them back. + int? productId = orderItemToUpdate.ProductId; + var rentalStartDate = orderItemToUpdate.RentalStartDateUtc; + var rentalEndDate = orderItemToUpdate.RentalEndDateUtc; + + orderItemDelta.Merge(orderItemToUpdate); + + orderItemToUpdate.ProductId = (int) productId; + orderItemToUpdate.RentalStartDateUtc = rentalStartDate; + orderItemToUpdate.RentalEndDateUtc = rentalEndDate; + + _orderService.UpdateOrder(order); + + CustomerActivityService.InsertActivity("UpdateOrderItem", + LocalizationService.GetResource("ActivityLog.UpdateOrderItem"), orderItemToUpdate); + + var orderItemsRootObject = new OrderItemsRootObject(); + + orderItemsRootObject.OrderItems.Add(orderItemToUpdate.ToDto()); + + var json = JsonFieldsSerializer.Serialize(orderItemsRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/orders/{orderId}/items/{orderItemId}")] + [ProducesResponseType(typeof(void), (int) HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int) HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int) HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteOrderItemById(int orderId, int orderItemId) + { + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var orderItem = _orderService.GetOrderItemById(orderItemId); + _orderService.DeleteOrderItem(orderItem); + + return new RawJsonActionResult("{}"); + } + + [HttpDelete] + [Route("/api/orders/{orderId}/items")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteAllOrderItemsForOrder(int orderId) + { + var order = _orderApiService.GetOrderById(orderId); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var orderItemsList = _orderService.GetOrderItems(order.Id).ToList(); + + foreach (var t in orderItemsList) + { + _orderService.DeleteOrderItem(t); + } + + return new RawJsonActionResult("{}"); + } + + private Product GetProduct(int? productId) + { + Product product = null; + + if (productId.HasValue) + { + var id = productId.Value; + + product = _productApiService.GetProductById(id); + } + + return product; + } + + private OrderItem PrepareDefaultOrderItemFromProduct(Order order, Product product) + { + var customer = CustomerService.GetCustomerById(order.CustomerId); + var presetQty = 1; + var presetPrice = + _priceCalculationService.GetFinalPrice(product, customer, decimal.Zero, true, presetQty); + + var presetPriceInclTax = + _taxService.GetProductPrice(product, presetPrice, true, customer, out _); + var presetPriceExclTax = + _taxService.GetProductPrice(product, presetPrice, false, customer, out _); + + var orderItem = new OrderItem + { + OrderItemGuid = new Guid(), + UnitPriceExclTax = presetPriceExclTax, + UnitPriceInclTax = presetPriceInclTax, + PriceInclTax = presetPriceInclTax, + PriceExclTax = presetPriceExclTax, + OriginalProductCost = _priceCalculationService.GetProductCost(product, null), + Quantity = presetQty, + ProductId = product.Id, + OrderId = order.Id + }; + + return orderItem; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/OrdersController.cs b/Controllers/OrdersController.cs similarity index 87% rename from Nop.Plugin.Api/Controllers/OrdersController.cs rename to Controllers/OrdersController.cs index 0348d21..1bf68dc 100644 --- a/Nop.Plugin.Api/Controllers/OrdersController.cs +++ b/Controllers/OrdersController.cs @@ -1,598 +1,599 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core; -using Nop.Core.Domain.Customers; -using Nop.Core.Domain.Orders; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.Factories; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.OrdersParameters; -using Nop.Plugin.Api.Services; -using Nop.Plugin.Api.Validators; -using Nop.Services.Catalog; -using Nop.Services.Common; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Orders; -using Nop.Services.Payments; -using Nop.Services.Security; -using Nop.Services.Shipping; -using Nop.Services.Stores; -using Microsoft.AspNetCore.Mvc; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class OrdersController : BaseApiController - { - private readonly IOrderApiService _orderApiService; - private readonly IProductService _productService; - private readonly IOrderProcessingService _orderProcessingService; - private readonly IOrderService _orderService; - private readonly IShoppingCartService _shoppingCartService; - private readonly IGenericAttributeService _genericAttributeService; - private readonly IShippingService _shippingService; - private readonly IDTOHelper _dtoHelper; - private readonly IProductAttributeConverter _productAttributeConverter; - private readonly IStoreContext _storeContext; - private readonly IFactory _factory; - - // We resolve the order settings this way because of the tests. - // The auto mocking does not support concreate types as dependencies. It supports only interfaces. - private OrderSettings _orderSettings; - - private OrderSettings OrderSettings => _orderSettings ?? (_orderSettings = EngineContext.Current.Resolve()); - - public OrdersController(IOrderApiService orderApiService, - IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IProductService productService, - IFactory factory, - IOrderProcessingService orderProcessingService, - IOrderService orderService, - IShoppingCartService shoppingCartService, - IGenericAttributeService genericAttributeService, - IStoreContext storeContext, - IShippingService shippingService, - IPictureService pictureService, - IDTOHelper dtoHelper, - IProductAttributeConverter productAttributeConverter) - : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, - storeService, discountService, customerActivityService, localizationService,pictureService) - { - _orderApiService = orderApiService; - _factory = factory; - _orderProcessingService = orderProcessingService; - _orderService = orderService; - _shoppingCartService = shoppingCartService; - _genericAttributeService = genericAttributeService; - _storeContext = storeContext; - _shippingService = shippingService; - _dtoHelper = dtoHelper; - _productService = productService; - _productAttributeConverter = productAttributeConverter; - } - - /// - /// Receive a list of all Orders - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/orders")] - [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrders(OrdersParametersModel parameters) - { - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); - } - - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "page", "Invalid limit parameter"); - } - - var storeId = _storeContext.CurrentStore.Id; - - var orders = _orderApiService.GetOrders(parameters.Ids, parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.Limit, parameters.Page, parameters.SinceId, - parameters.Status, parameters.PaymentStatus, parameters.ShippingStatus, - parameters.CustomerId, storeId); - - IList ordersAsDtos = orders.Select(x => _dtoHelper.PrepareOrderDTO(x)).ToList(); - - var ordersRootObject = new OrdersRootObject() - { - Orders = ordersAsDtos - }; - - var json = JsonFieldsSerializer.Serialize(ordersRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a count of all Orders - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/orders/count")] - [ProducesResponseType(typeof(OrdersCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrdersCount(OrdersCountParametersModel parameters) - { - var storeId = _storeContext.CurrentStore.Id; - - var ordersCount = _orderApiService.GetOrdersCount(parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.Status, - parameters.PaymentStatus, parameters.ShippingStatus, parameters.CustomerId, storeId); - - var ordersCountRootObject = new OrdersCountRootObject() - { - Count = ordersCount - }; - - return Ok(ordersCountRootObject); - } - - /// - /// Retrieve order by spcified id - /// - /// /// Id of the order - /// Fields from the order you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/orders/{id}")] - [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrderById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var order = _orderApiService.GetOrderById(id); - - if (order == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var ordersRootObject = new OrdersRootObject(); - - var orderDto = _dtoHelper.PrepareOrderDTO(order); - ordersRootObject.Orders.Add(orderDto); - - var json = JsonFieldsSerializer.Serialize(ordersRootObject, fields); - - return new RawJsonActionResult(json); - } - - /// - /// Retrieve all orders for customer - /// - /// Id of the customer whoes orders you want to get - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/orders/customer/{customer_id}")] - [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetOrdersByCustomerId(int customerId) - { - IList ordersForCustomer = _orderApiService.GetOrdersByCustomerId(customerId).Select(x => _dtoHelper.PrepareOrderDTO(x)).ToList(); - - var ordersRootObject = new OrdersRootObject() - { - Orders = ordersForCustomer - }; - - return Ok(ordersRootObject); - } - - [HttpPost] - [Route("/api/orders")] - [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - public IActionResult CreateOrder([ModelBinder(typeof(JsonModelBinder))] Delta orderDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - if (orderDelta.Dto.CustomerId == null) - { - return Error(); - } - - // We doesn't have to check for value because this is done by the order validator. - var customer = CustomerService.GetCustomerById(orderDelta.Dto.CustomerId.Value); - - if (customer == null) - { - return Error(HttpStatusCode.NotFound, "customer", "not found"); - } - - var shippingRequired = false; - - if (orderDelta.Dto.OrderItems != null) - { - var shouldReturnError = AddOrderItemsToCart(orderDelta.Dto.OrderItems, customer, orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id); - if (shouldReturnError) - { - return Error(HttpStatusCode.BadRequest); - } - - shippingRequired = IsShippingAddressRequired(orderDelta.Dto.OrderItems); - } - - if (shippingRequired) - { - var isValid = true; - - isValid &= SetShippingOption(orderDelta.Dto.ShippingRateComputationMethodSystemName, - orderDelta.Dto.ShippingMethod, - orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id, - customer, - BuildShoppingCartItemsFromOrderItemDtos(orderDelta.Dto.OrderItems.ToList(), - customer.Id, - orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id)); - - if (!isValid) - { - return Error(HttpStatusCode.BadRequest); - } - } - - var newOrder = _factory.Initialize(); - orderDelta.Merge(newOrder); - - customer.BillingAddress = newOrder.BillingAddress; - customer.ShippingAddress = newOrder.ShippingAddress; - - // If the customer has something in the cart it will be added too. Should we clear the cart first? - newOrder.Customer = customer; - - // The default value will be the currentStore.id, but if it isn't passed in the json we need to set it by hand. - if (!orderDelta.Dto.StoreId.HasValue) - { - newOrder.StoreId = _storeContext.CurrentStore.Id; - } - - var placeOrderResult = PlaceOrder(newOrder, customer); - - if (!placeOrderResult.Success) - { - foreach (var error in placeOrderResult.Errors) - { - ModelState.AddModelError("order placement", error); - } - - return Error(HttpStatusCode.BadRequest); - } - - CustomerActivityService.InsertActivity("AddNewOrder", - LocalizationService.GetResource("ActivityLog.AddNewOrder"), newOrder); - - var ordersRootObject = new OrdersRootObject(); - - var placedOrderDto = _dtoHelper.PrepareOrderDTO(placeOrderResult.PlacedOrder); - - ordersRootObject.Orders.Add(placedOrderDto); - - var json = JsonFieldsSerializer.Serialize(ordersRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/orders/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteOrder(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var orderToDelete = _orderApiService.GetOrderById(id); - - if (orderToDelete == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - _orderProcessingService.DeleteOrder(orderToDelete); - - //activity log - CustomerActivityService.InsertActivity("DeleteOrder", LocalizationService.GetResource("ActivityLog.DeleteOrder"), orderToDelete); - - return new RawJsonActionResult("{}"); - } - - [HttpPut] - [Route("/api/orders/{id}")] - [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - public IActionResult UpdateOrder([ModelBinder(typeof(JsonModelBinder))] Delta orderDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var currentOrder = _orderApiService.GetOrderById(orderDelta.Dto.Id); - - if (currentOrder == null) - { - return Error(HttpStatusCode.NotFound, "order", "not found"); - } - - var customer = currentOrder.Customer; - - var shippingRequired = currentOrder.OrderItems.Any(item => !item.Product.IsFreeShipping); - - if (shippingRequired) - { - var isValid = true; - - if (!string.IsNullOrEmpty(orderDelta.Dto.ShippingRateComputationMethodSystemName) || - !string.IsNullOrEmpty(orderDelta.Dto.ShippingMethod)) - { - var storeId = orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id; - - isValid &= SetShippingOption(orderDelta.Dto.ShippingRateComputationMethodSystemName ?? currentOrder.ShippingRateComputationMethodSystemName, - orderDelta.Dto.ShippingMethod, - storeId, - customer, BuildShoppingCartItemsFromOrderItems(currentOrder.OrderItems.ToList(), customer.Id, storeId)); - } - - if (isValid) - { - currentOrder.ShippingMethod = orderDelta.Dto.ShippingMethod; - } - else - { - return Error(HttpStatusCode.BadRequest); - } - } - - orderDelta.Merge(currentOrder); - - customer.BillingAddress = currentOrder.BillingAddress; - customer.ShippingAddress = currentOrder.ShippingAddress; - - _orderService.UpdateOrder(currentOrder); - - CustomerActivityService.InsertActivity("UpdateOrder", - LocalizationService.GetResource("ActivityLog.UpdateOrder"), currentOrder); - - var ordersRootObject = new OrdersRootObject(); - - var placedOrderDto = _dtoHelper.PrepareOrderDTO(currentOrder); - placedOrderDto.ShippingMethod = orderDelta.Dto.ShippingMethod; - - ordersRootObject.Orders.Add(placedOrderDto); - - var json = JsonFieldsSerializer.Serialize(ordersRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - private bool SetShippingOption(string shippingRateComputationMethodSystemName, string shippingOptionName, int storeId, Customer customer, List shoppingCartItems) - { - var isValid = true; - - if (string.IsNullOrEmpty(shippingRateComputationMethodSystemName)) - { - isValid = false; - - ModelState.AddModelError("shipping_rate_computation_method_system_name", - "Please provide shipping_rate_computation_method_system_name"); - } - else if (string.IsNullOrEmpty(shippingOptionName)) - { - isValid = false; - - ModelState.AddModelError("shipping_option_name", "Please provide shipping_option_name"); - } - else - { - var shippingOptionResponse = _shippingService.GetShippingOptions(shoppingCartItems, customer.ShippingAddress, customer, - shippingRateComputationMethodSystemName, storeId); - - if (shippingOptionResponse.Success) - { - var shippingOptions = shippingOptionResponse.ShippingOptions.ToList(); - - var shippingOption = shippingOptions - .Find(so => !string.IsNullOrEmpty(so.Name) && so.Name.Equals(shippingOptionName, StringComparison.InvariantCultureIgnoreCase)); - - _genericAttributeService.SaveAttribute(customer, - NopCustomerDefaults.SelectedShippingOptionAttribute, - shippingOption, storeId); - } - else - { - isValid = false; - - foreach (var errorMessage in shippingOptionResponse.Errors) - { - ModelState.AddModelError("shipping_option", errorMessage); - } - } - } - - return isValid; - } - - private List BuildShoppingCartItemsFromOrderItems(List orderItems, int customerId, int storeId) - { - var shoppingCartItems = new List(); - - foreach (var orderItem in orderItems) - { - shoppingCartItems.Add(new ShoppingCartItem() - { - ProductId = orderItem.ProductId, - CustomerId = customerId, - Quantity = orderItem.Quantity, - RentalStartDateUtc = orderItem.RentalStartDateUtc, - RentalEndDateUtc = orderItem.RentalEndDateUtc, - StoreId = storeId, - Product = orderItem.Product, - ShoppingCartType = ShoppingCartType.ShoppingCart - }); - } - - return shoppingCartItems; - } - - private List BuildShoppingCartItemsFromOrderItemDtos(List orderItemDtos, int customerId, int storeId) - { - var shoppingCartItems = new List(); - - foreach (var orderItem in orderItemDtos) - { - if (orderItem.ProductId != null) - { - shoppingCartItems.Add(new ShoppingCartItem() - { - ProductId = orderItem.ProductId.Value, // required field - CustomerId = customerId, - Quantity = orderItem.Quantity ?? 1, - RentalStartDateUtc = orderItem.RentalStartDateUtc, - RentalEndDateUtc = orderItem.RentalEndDateUtc, - StoreId = storeId, - Product = _productService.GetProductById(orderItem.ProductId.Value), - ShoppingCartType = ShoppingCartType.ShoppingCart - }); - } - } - - return shoppingCartItems; - } - - private PlaceOrderResult PlaceOrder(Order newOrder, Customer customer) - { - var processPaymentRequest = new ProcessPaymentRequest - { - StoreId = newOrder.StoreId, - CustomerId = customer.Id, - PaymentMethodSystemName = newOrder.PaymentMethodSystemName - }; - - - var placeOrderResult = _orderProcessingService.PlaceOrder(processPaymentRequest); - - return placeOrderResult; - } - - private bool IsShippingAddressRequired(ICollection orderItems) - { - var shippingAddressRequired = false; - - foreach (var orderItem in orderItems) - { - if (orderItem.ProductId != null) - { - var product = _productService.GetProductById(orderItem.ProductId.Value); - - shippingAddressRequired |= product.IsShipEnabled; - } - } - - return shippingAddressRequired; - } - - private bool AddOrderItemsToCart(ICollection orderItems, Customer customer, int storeId) - { - var shouldReturnError = false; - - foreach (var orderItem in orderItems) - { - if (orderItem.ProductId != null) - { - var product = _productService.GetProductById(orderItem.ProductId.Value); - - if (!product.IsRental) - { - orderItem.RentalStartDateUtc = null; - orderItem.RentalEndDateUtc = null; - } - - var attributesXml = _productAttributeConverter.ConvertToXml(orderItem.Attributes.ToList(), product.Id); - - var errors = _shoppingCartService.AddToCart(customer, product, - ShoppingCartType.ShoppingCart, storeId,attributesXml, - 0M, orderItem.RentalStartDateUtc, orderItem.RentalEndDateUtc, - orderItem.Quantity ?? 1); - - if (errors.Count > 0) - { - foreach (var error in errors) - { - ModelState.AddModelError("order", error); - } - - shouldReturnError = true; - } - } - } - - return shouldReturnError; - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Orders; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.DTO.Orders; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.OrdersParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Common; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Orders; +using Nop.Services.Payments; +using Nop.Services.Security; +using Nop.Services.Shipping; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + + public class OrdersController : BaseApiController + { + private readonly IOrderApiService _orderApiService; + private readonly IProductService _productService; + private readonly IOrderProcessingService _orderProcessingService; + private readonly IOrderService _orderService; + private readonly IShoppingCartService _shoppingCartService; + private readonly IGenericAttributeService _genericAttributeService; + private readonly IShippingService _shippingService; + private readonly IDTOHelper _dtoHelper; + private readonly IProductAttributeConverter _productAttributeConverter; + private readonly IStoreContext _storeContext; + private readonly IFactory _factory; + + // We resolve the order settings this way because of the tests. + // The auto mocking does not support concreate types as dependencies. It supports only interfaces. + private OrderSettings _orderSettings; + + private OrderSettings OrderSettings => _orderSettings ?? (_orderSettings = EngineContext.Current.Resolve()); + + public OrdersController(IOrderApiService orderApiService, + IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IProductService productService, + IFactory factory, + IOrderProcessingService orderProcessingService, + IOrderService orderService, + IShoppingCartService shoppingCartService, + IGenericAttributeService genericAttributeService, + IStoreContext storeContext, + IShippingService shippingService, + IPictureService pictureService, + IDTOHelper dtoHelper, + IProductAttributeConverter productAttributeConverter) + : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, + storeService, discountService, customerActivityService, localizationService,pictureService) + { + _orderApiService = orderApiService; + _factory = factory; + _orderProcessingService = orderProcessingService; + _orderService = orderService; + _shoppingCartService = shoppingCartService; + _genericAttributeService = genericAttributeService; + _storeContext = storeContext; + _shippingService = shippingService; + _dtoHelper = dtoHelper; + _productService = productService; + _productAttributeConverter = productAttributeConverter; + } + + /// + /// Receive a list of all Orders + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/orders")] + [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrders(OrdersParametersModel parameters) + { + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid page parameter"); + } + + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "page", "Invalid limit parameter"); + } + + var storeId = _storeContext.CurrentStore.Id; + + var orders = _orderApiService.GetOrders(parameters.Ids, parameters.CreatedAtMin, + parameters.CreatedAtMax, + parameters.Limit, parameters.Page, parameters.SinceId, + parameters.Status, parameters.PaymentStatus, parameters.ShippingStatus, + parameters.CustomerId, storeId); + + IList ordersAsDtos = orders.Select(x => _dtoHelper.PrepareOrderDTO(x)).ToList(); + + var ordersRootObject = new OrdersRootObject() + { + Orders = ordersAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(ordersRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a count of all Orders + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/orders/count")] + [ProducesResponseType(typeof(OrdersCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrdersCount(OrdersCountParametersModel parameters) + { + var storeId = _storeContext.CurrentStore.Id; + + var ordersCount = _orderApiService.GetOrdersCount(parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.Status, + parameters.PaymentStatus, parameters.ShippingStatus, parameters.CustomerId, storeId, + parameters.SinceId); + + var ordersCountRootObject = new OrdersCountRootObject() + { + Count = ordersCount + }; + + return Ok(ordersCountRootObject); + } + + /// + /// Retrieve order by spcified id + /// + /// /// Id of the order + /// Fields from the order you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/orders/{id}")] + [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrderById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var order = _orderApiService.GetOrderById(id); + + if (order == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var ordersRootObject = new OrdersRootObject(); + + var orderDto = _dtoHelper.PrepareOrderDTO(order); + ordersRootObject.Orders.Add(orderDto); + + var json = JsonFieldsSerializer.Serialize(ordersRootObject, fields); + + return new RawJsonActionResult(json); + } + + /// + /// Retrieve all orders for customer + /// + /// Id of the customer whoes orders you want to get + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/orders/customer/{customer_id}")] + [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetOrdersByCustomerId(int customerId) + { + IList ordersForCustomer = _orderApiService.GetOrdersByCustomerId(customerId).Select(x => _dtoHelper.PrepareOrderDTO(x)).ToList(); + + var ordersRootObject = new OrdersRootObject() + { + Orders = ordersForCustomer + }; + + return Ok(ordersRootObject); + } + + [HttpPost] + [Route("/api/orders")] + [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult CreateOrder([ModelBinder(typeof(JsonModelBinder))] Delta orderDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + if (orderDelta.Dto.CustomerId == null) + { + return Error(); + } + + // We doesn't have to check for value because this is done by the order validator. + var customer = CustomerService.GetCustomerById(orderDelta.Dto.CustomerId.Value); + + if (customer == null) + { + return Error(HttpStatusCode.NotFound, "customer", "not found"); + } + + var shippingRequired = false; + + if (orderDelta.Dto.OrderItems != null) + { + var shouldReturnError = AddOrderItemsToCart(orderDelta.Dto.OrderItems, customer, orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id); + if (shouldReturnError) + { + return Error(HttpStatusCode.BadRequest); + } + + shippingRequired = IsShippingAddressRequired(orderDelta.Dto.OrderItems); + } + + if (shippingRequired) + { + var isValid = true; + + isValid &= SetShippingOption(orderDelta.Dto.ShippingRateComputationMethodSystemName, + orderDelta.Dto.ShippingMethod, + orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id, + customer, + BuildShoppingCartItemsFromOrderItemDtos(orderDelta.Dto.OrderItems.ToList(), + customer.Id, + orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id)); + + if (!isValid) + { + return Error(HttpStatusCode.BadRequest); + } + } + + var newOrder = _factory.Initialize(); + orderDelta.Merge(newOrder); + + customer.BillingAddressId = newOrder.BillingAddressId = orderDelta.Dto.BillingAddress.Id; + customer.ShippingAddressId = newOrder.ShippingAddressId = orderDelta.Dto.ShippingAddress.Id; + + + // If the customer has something in the cart it will be added too. Should we clear the cart first? + newOrder.CustomerId = customer.Id; + + // The default value will be the currentStore.id, but if it isn't passed in the json we need to set it by hand. + if (!orderDelta.Dto.StoreId.HasValue) + { + newOrder.StoreId = _storeContext.CurrentStore.Id; + } + + var placeOrderResult = PlaceOrder(newOrder, customer); + + if (!placeOrderResult.Success) + { + foreach (var error in placeOrderResult.Errors) + { + ModelState.AddModelError("order placement", error); + } + + return Error(HttpStatusCode.BadRequest); + } + + CustomerActivityService.InsertActivity("AddNewOrder", + LocalizationService.GetResource("ActivityLog.AddNewOrder"), newOrder); + + var ordersRootObject = new OrdersRootObject(); + + var placedOrderDto = _dtoHelper.PrepareOrderDTO(placeOrderResult.PlacedOrder); + + ordersRootObject.Orders.Add(placedOrderDto); + + var json = JsonFieldsSerializer.Serialize(ordersRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/orders/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteOrder(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var orderToDelete = _orderApiService.GetOrderById(id); + + if (orderToDelete == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + _orderProcessingService.DeleteOrder(orderToDelete); + + //activity log + CustomerActivityService.InsertActivity("DeleteOrder", LocalizationService.GetResource("ActivityLog.DeleteOrder"), orderToDelete); + + return new RawJsonActionResult("{}"); + } + + [HttpPut] + [Route("/api/orders/{id}")] + [ProducesResponseType(typeof(OrdersRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult UpdateOrder([ModelBinder(typeof(JsonModelBinder))] Delta orderDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var currentOrder = _orderApiService.GetOrderById(orderDelta.Dto.Id); + + if (currentOrder == null) + { + return Error(HttpStatusCode.NotFound, "order", "not found"); + } + + var customer = CustomerService.GetCustomerById(currentOrder.CustomerId); + + var shippingRequired = _orderService.GetOrderItems(currentOrder.Id).Any(item => !_productService.GetProductById(item.Id).IsFreeShipping); + + if (shippingRequired) + { + var isValid = true; + + if (!string.IsNullOrEmpty(orderDelta.Dto.ShippingRateComputationMethodSystemName) || + !string.IsNullOrEmpty(orderDelta.Dto.ShippingMethod)) + { + var storeId = orderDelta.Dto.StoreId ?? _storeContext.CurrentStore.Id; + + isValid &= SetShippingOption(orderDelta.Dto.ShippingRateComputationMethodSystemName ?? currentOrder.ShippingRateComputationMethodSystemName, + orderDelta.Dto.ShippingMethod, + storeId, + customer, BuildShoppingCartItemsFromOrderItems(_orderService.GetOrderItems(currentOrder.Id).ToList(), customer.Id, storeId)); + } + + if (isValid) + { + currentOrder.ShippingMethod = orderDelta.Dto.ShippingMethod; + } + else + { + return Error(HttpStatusCode.BadRequest); + } + } + + orderDelta.Merge(currentOrder); + + customer.BillingAddressId = currentOrder.BillingAddressId = orderDelta.Dto.BillingAddress.Id; + customer.ShippingAddressId = currentOrder.ShippingAddressId = orderDelta.Dto.ShippingAddress.Id; + + + _orderService.UpdateOrder(currentOrder); + + CustomerActivityService.InsertActivity("UpdateOrder", + LocalizationService.GetResource("ActivityLog.UpdateOrder"), currentOrder); + + var ordersRootObject = new OrdersRootObject(); + + var placedOrderDto = _dtoHelper.PrepareOrderDTO(currentOrder); + placedOrderDto.ShippingMethod = orderDelta.Dto.ShippingMethod; + + ordersRootObject.Orders.Add(placedOrderDto); + + var json = JsonFieldsSerializer.Serialize(ordersRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + private bool SetShippingOption(string shippingRateComputationMethodSystemName, + string shippingOptionName, + int storeId, + Customer customer, + List shoppingCartItems) + { + var isValid = true; + + if (string.IsNullOrEmpty(shippingRateComputationMethodSystemName)) + { + isValid = false; + + ModelState.AddModelError("shipping_rate_computation_method_system_name", + "Please provide shipping_rate_computation_method_system_name"); + } + else if (string.IsNullOrEmpty(shippingOptionName)) + { + isValid = false; + + ModelState.AddModelError("shipping_option_name", "Please provide shipping_option_name"); + } + else + { + var shippingOptionResponse = _shippingService.GetShippingOptions(shoppingCartItems, CustomerService.GetCustomerShippingAddress(customer), customer, + shippingRateComputationMethodSystemName, storeId); + + if (shippingOptionResponse.Success) + { + var shippingOptions = shippingOptionResponse.ShippingOptions.ToList(); + + var shippingOption = shippingOptions + .Find(so => !string.IsNullOrEmpty(so.Name) && so.Name.Equals(shippingOptionName, StringComparison.InvariantCultureIgnoreCase)); + + _genericAttributeService.SaveAttribute(customer, + NopCustomerDefaults.SelectedShippingOptionAttribute, + shippingOption, storeId); + } + else + { + isValid = false; + + foreach (var errorMessage in shippingOptionResponse.Errors) + { + ModelState.AddModelError("shipping_option", errorMessage); + } + } + } + + return isValid; + } + + private List BuildShoppingCartItemsFromOrderItems(List orderItems, int customerId, int storeId) + { + var shoppingCartItems = new List(); + + foreach (var orderItem in orderItems) + { + shoppingCartItems.Add(new ShoppingCartItem + { + ProductId = orderItem.ProductId, + CustomerId = customerId, + Quantity = orderItem.Quantity, + RentalStartDateUtc = orderItem.RentalStartDateUtc, + RentalEndDateUtc = orderItem.RentalEndDateUtc, + StoreId = storeId, + ShoppingCartType = ShoppingCartType.ShoppingCart + }); + } + + return shoppingCartItems; + } + + private List BuildShoppingCartItemsFromOrderItemDtos(List orderItemDtos, int customerId, int storeId) + { + var shoppingCartItems = new List(); + + foreach (var orderItem in orderItemDtos) + { + if (orderItem.ProductId != null) + { + shoppingCartItems.Add(new ShoppingCartItem + { + ProductId = orderItem.ProductId.Value, // required field + CustomerId = customerId, + Quantity = orderItem.Quantity ?? 1, + RentalStartDateUtc = orderItem.RentalStartDateUtc, + RentalEndDateUtc = orderItem.RentalEndDateUtc, + StoreId = storeId, + ShoppingCartType = ShoppingCartType.ShoppingCart + }); + } + } + + return shoppingCartItems; + } + + private PlaceOrderResult PlaceOrder(Order newOrder, Customer customer) + { + var processPaymentRequest = new ProcessPaymentRequest + { + StoreId = newOrder.StoreId, + CustomerId = customer.Id, + PaymentMethodSystemName = newOrder.PaymentMethodSystemName + }; + + + var placeOrderResult = _orderProcessingService.PlaceOrder(processPaymentRequest); + + return placeOrderResult; + } + + private bool IsShippingAddressRequired(ICollection orderItems) + { + var shippingAddressRequired = false; + + foreach (var orderItem in orderItems) + { + if (orderItem.ProductId != null) + { + var product = _productService.GetProductById(orderItem.ProductId.Value); + + shippingAddressRequired |= product.IsShipEnabled; + } + } + + return shippingAddressRequired; + } + + private bool AddOrderItemsToCart(ICollection orderItems, Customer customer, int storeId) + { + var shouldReturnError = false; + + foreach (var orderItem in orderItems) + { + if (orderItem.ProductId != null) + { + var product = _productService.GetProductById(orderItem.ProductId.Value); + + if (!product.IsRental) + { + orderItem.RentalStartDateUtc = null; + orderItem.RentalEndDateUtc = null; + } + + var attributesXml = _productAttributeConverter.ConvertToXml(orderItem.Attributes.ToList(), product.Id); + + var errors = _shoppingCartService.AddToCart(customer, product, + ShoppingCartType.ShoppingCart, storeId,attributesXml, + 0M, orderItem.RentalStartDateUtc, orderItem.RentalEndDateUtc, + orderItem.Quantity ?? 1); + + if (errors.Count > 0) + { + foreach (var error in errors) + { + ModelState.AddModelError("order", error); + } + + shouldReturnError = true; + } + } + } + + return shouldReturnError; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/ProductAttributesController.cs b/Controllers/ProductAttributesController.cs similarity index 95% rename from Nop.Plugin.Api/Controllers/ProductAttributesController.cs rename to Controllers/ProductAttributesController.cs index 4b95520..72d1d78 100644 --- a/Nop.Plugin.Api/Controllers/ProductAttributesController.cs +++ b/Controllers/ProductAttributesController.cs @@ -1,263 +1,261 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.DTOs.ProductAttributes; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.ProductAttributes; -using Nop.Plugin.Api.JSON.Serializers; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; -using System.Collections.Generic; -using System.Linq; -using System.Net; - -namespace Nop.Plugin.Api.Controllers -{ - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class ProductAttributesController : BaseApiController - { - private readonly IProductAttributeService _productAttributeService; - private readonly IProductAttributesApiService _productAttributesApiService; - private readonly IDTOHelper _dtoHelper; - - public ProductAttributesController(IJsonFieldsSerializer jsonFieldsSerializer, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IAclService aclService, - IStoreMappingService storeMappingService, - IStoreService storeService, - ICustomerService customerService, - IDiscountService discountService, - IPictureService pictureService, - IProductAttributeService productAttributeService, - IProductAttributesApiService productAttributesApiService, - IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) - { - _productAttributeService = productAttributeService; - _productAttributesApiService = productAttributesApiService; - _dtoHelper = dtoHelper; - } - - /// - /// Receive a list of all product attributes - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/productattributes")] - [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProductAttributes(ProductAttributesParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); - } - - var allProductAttributes = _productAttributesApiService.GetProductAttributes(parameters.Limit, parameters.Page, parameters.SinceId); - - IList productAttributesAsDtos = allProductAttributes.Select(productAttribute => _dtoHelper.PrepareProductAttributeDTO(productAttribute)).ToList(); - - var productAttributesRootObject = new ProductAttributesRootObjectDto() - { - ProductAttributes = productAttributesAsDtos - }; - - var json = JsonFieldsSerializer.Serialize(productAttributesRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a count of all product attributes - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/productattributes/count")] - [ProducesResponseType(typeof(ProductAttributesCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProductAttributesCount() - { - var allProductAttributesCount = _productAttributesApiService.GetProductAttributesCount(); - - var productAttributesCountRootObject = new ProductAttributesCountRootObject() - { - Count = allProductAttributesCount - }; - - return Ok(productAttributesCountRootObject); - } - - /// - /// Retrieve product attribute by spcified id - /// - /// Id of the product attribute - /// Fields from the product attribute you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/productattributes/{id}")] - [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProductAttributeById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var productAttribute = _productAttributesApiService.GetById(id); - - if (productAttribute == null) - { - return Error(HttpStatusCode.NotFound, "product attribute", "not found"); - } - - var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); - - var productAttributesRootObject = new ProductAttributesRootObjectDto(); - - productAttributesRootObject.ProductAttributes.Add(productAttributeDto); - - var json = JsonFieldsSerializer.Serialize(productAttributesRootObject, fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/productattributes")] - [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult CreateProductAttribute([ModelBinder(typeof(JsonModelBinder))] Delta productAttributeDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - // Inserting the new product - var productAttribute = new ProductAttribute(); - productAttributeDelta.Merge(productAttribute); - - _productAttributeService.InsertProductAttribute(productAttribute); - - CustomerActivityService.InsertActivity("AddNewProductAttribute", - LocalizationService.GetResource("ActivityLog.AddNewProductAttribute"), productAttribute); - - // Preparing the result dto of the new product - var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); - - var productAttributesRootObjectDto = new ProductAttributesRootObjectDto(); - - productAttributesRootObjectDto.ProductAttributes.Add(productAttributeDto); - - var json = JsonFieldsSerializer.Serialize(productAttributesRootObjectDto, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/productattributes/{id}")] - [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult UpdateProductAttribute([ModelBinder(typeof(JsonModelBinder))] Delta productAttributeDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var productAttribute = _productAttributesApiService.GetById(productAttributeDelta.Dto.Id); - - if (productAttribute == null) - { - return Error(HttpStatusCode.NotFound, "product attribute", "not found"); - } - - productAttributeDelta.Merge(productAttribute); - - - _productAttributeService.UpdateProductAttribute(productAttribute); - - CustomerActivityService.InsertActivity("EditProductAttribute", - LocalizationService.GetResource("ActivityLog.EditProductAttribute"), productAttribute); - - // Preparing the result dto of the new product attribute - var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); - - var productAttributesRootObjectDto = new ProductAttributesRootObjectDto(); - - productAttributesRootObjectDto.ProductAttributes.Add(productAttributeDto); - - var json = JsonFieldsSerializer.Serialize(productAttributesRootObjectDto, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/productattributes/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteProductAttribute(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var productAttribute = _productAttributesApiService.GetById(id); - - if (productAttribute == null) - { - return Error(HttpStatusCode.NotFound, "product attribute", "not found"); - } - - _productAttributeService.DeleteProductAttribute(productAttribute); - - //activity log - CustomerActivityService.InsertActivity("DeleteProductAttribute", LocalizationService.GetResource("ActivityLog.DeleteProductAttribute"), productAttribute); - - return new RawJsonActionResult("{}"); - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.ProductAttributes; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.ProductAttributes; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class ProductAttributesController : BaseApiController + { + private readonly IProductAttributeService _productAttributeService; + private readonly IProductAttributesApiService _productAttributesApiService; + private readonly IDTOHelper _dtoHelper; + + public ProductAttributesController(IJsonFieldsSerializer jsonFieldsSerializer, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IAclService aclService, + IStoreMappingService storeMappingService, + IStoreService storeService, + ICustomerService customerService, + IDiscountService discountService, + IPictureService pictureService, + IProductAttributeService productAttributeService, + IProductAttributesApiService productAttributesApiService, + IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) + { + _productAttributeService = productAttributeService; + _productAttributesApiService = productAttributesApiService; + _dtoHelper = dtoHelper; + } + + /// + /// Receive a list of all product attributes + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/productattributes")] + [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProductAttributes(ProductAttributesParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); + } + + var allProductAttributes = _productAttributesApiService.GetProductAttributes(parameters.Limit, parameters.Page, parameters.SinceId); + + IList productAttributesAsDtos = allProductAttributes.Select(productAttribute => _dtoHelper.PrepareProductAttributeDTO(productAttribute)).ToList(); + + var productAttributesRootObject = new ProductAttributesRootObjectDto() + { + ProductAttributes = productAttributesAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(productAttributesRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a count of all product attributes + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/productattributes/count")] + [ProducesResponseType(typeof(ProductAttributesCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProductAttributesCount() + { + var allProductAttributesCount = _productAttributesApiService.GetProductAttributesCount(); + + var productAttributesCountRootObject = new ProductAttributesCountRootObject() + { + Count = allProductAttributesCount + }; + + return Ok(productAttributesCountRootObject); + } + + /// + /// Retrieve product attribute by spcified id + /// + /// Id of the product attribute + /// Fields from the product attribute you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/productattributes/{id}")] + [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProductAttributeById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var productAttribute = _productAttributesApiService.GetById(id); + + if (productAttribute == null) + { + return Error(HttpStatusCode.NotFound, "product attribute", "not found"); + } + + var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); + + var productAttributesRootObject = new ProductAttributesRootObjectDto(); + + productAttributesRootObject.ProductAttributes.Add(productAttributeDto); + + var json = JsonFieldsSerializer.Serialize(productAttributesRootObject, fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/productattributes")] + [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult CreateProductAttribute([ModelBinder(typeof(JsonModelBinder))] Delta productAttributeDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + // Inserting the new product + var productAttribute = new ProductAttribute(); + productAttributeDelta.Merge(productAttribute); + + _productAttributeService.InsertProductAttribute(productAttribute); + + CustomerActivityService.InsertActivity("AddNewProductAttribute", + LocalizationService.GetResource("ActivityLog.AddNewProductAttribute"), productAttribute); + + // Preparing the result dto of the new product + var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); + + var productAttributesRootObjectDto = new ProductAttributesRootObjectDto(); + + productAttributesRootObjectDto.ProductAttributes.Add(productAttributeDto); + + var json = JsonFieldsSerializer.Serialize(productAttributesRootObjectDto, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/productattributes/{id}")] + [ProducesResponseType(typeof(ProductAttributesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult UpdateProductAttribute([ModelBinder(typeof(JsonModelBinder))] Delta productAttributeDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var productAttribute = _productAttributesApiService.GetById(productAttributeDelta.Dto.Id); + + if (productAttribute == null) + { + return Error(HttpStatusCode.NotFound, "product attribute", "not found"); + } + + productAttributeDelta.Merge(productAttribute); + + + _productAttributeService.UpdateProductAttribute(productAttribute); + + CustomerActivityService.InsertActivity("EditProductAttribute", + LocalizationService.GetResource("ActivityLog.EditProductAttribute"), productAttribute); + + // Preparing the result dto of the new product attribute + var productAttributeDto = _dtoHelper.PrepareProductAttributeDTO(productAttribute); + + var productAttributesRootObjectDto = new ProductAttributesRootObjectDto(); + + productAttributesRootObjectDto.ProductAttributes.Add(productAttributeDto); + + var json = JsonFieldsSerializer.Serialize(productAttributesRootObjectDto, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/productattributes/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteProductAttribute(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var productAttribute = _productAttributesApiService.GetById(id); + + if (productAttribute == null) + { + return Error(HttpStatusCode.NotFound, "product attribute", "not found"); + } + + _productAttributeService.DeleteProductAttribute(productAttribute); + + //activity log + CustomerActivityService.InsertActivity("DeleteProductAttribute", LocalizationService.GetResource("ActivityLog.DeleteProductAttribute"), productAttribute); + + return new RawJsonActionResult("{}"); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/ProductCategoryMappingsController.cs b/Controllers/ProductCategoryMappingsController.cs similarity index 94% rename from Nop.Plugin.Api/Controllers/ProductCategoryMappingsController.cs rename to Controllers/ProductCategoryMappingsController.cs index 92c0e42..8a37ab9 100644 --- a/Nop.Plugin.Api/Controllers/ProductCategoryMappingsController.cs +++ b/Controllers/ProductCategoryMappingsController.cs @@ -1,317 +1,313 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.ProductCategoryMappingsParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class ProductCategoryMappingsController : BaseApiController - { - private readonly IProductCategoryMappingsApiService _productCategoryMappingsService; - private readonly ICategoryService _categoryService; - private readonly ICategoryApiService _categoryApiService; - private readonly IProductApiService _productApiService; - - public ProductCategoryMappingsController(IProductCategoryMappingsApiService productCategoryMappingsService, - ICategoryService categoryService, - IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - ICategoryApiService categoryApiService, - IProductApiService productApiService, - IPictureService pictureService) - : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService,pictureService) - { - _productCategoryMappingsService = productCategoryMappingsService; - _categoryService = categoryService; - _categoryApiService = categoryApiService; - _productApiService = productApiService; - } - - /// - /// Receive a list of all Product-Category mappings - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/product_category_mappings")] - [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetMappings(ProductCategoryMappingsParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); - } - - IList mappingsAsDtos = - _productCategoryMappingsService.GetMappings(parameters.ProductId, - parameters.CategoryId, - parameters.Limit, - parameters.Page, - parameters.SinceId).Select(x => x.ToDto()).ToList(); - - var productCategoryMappingRootObject = new ProductCategoryMappingsRootObject() - { - ProductCategoryMappingDtos = mappingsAsDtos - }; - - var json = JsonFieldsSerializer.Serialize(productCategoryMappingRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a count of all Product-Category mappings - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/product_category_mappings/count")] - [ProducesResponseType(typeof(ProductCategoryMappingsCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetMappingsCount(ProductCategoryMappingsCountParametersModel parameters) - { - if (parameters.ProductId < 0) - { - return Error(HttpStatusCode.BadRequest, "product_id", "invalid product_id"); - } - - if (parameters.CategoryId < 0) - { - return Error(HttpStatusCode.BadRequest, "category_id", "invalid category_id"); - } - - var mappingsCount = _productCategoryMappingsService.GetMappingsCount(parameters.ProductId, - parameters.CategoryId); - - var productCategoryMappingsCountRootObject = new ProductCategoryMappingsCountRootObject() - { - Count = mappingsCount - }; - - return Ok(productCategoryMappingsCountRootObject); - } - - /// - /// Retrieve Product-Category mappings by spcified id - /// - /// /// Id of the Product-Category mapping - /// Fields from the Product-Category mapping you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/product_category_mappings/{id}")] - [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetMappingById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var mapping = _productCategoryMappingsService.GetById(id); - - if (mapping == null) - { - return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); - } - - var productCategoryMappingsRootObject = new ProductCategoryMappingsRootObject(); - productCategoryMappingsRootObject.ProductCategoryMappingDtos.Add(mapping.ToDto()); - - var json = JsonFieldsSerializer.Serialize(productCategoryMappingsRootObject, fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/product_category_mappings")] - [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - public IActionResult CreateProductCategoryMapping([ModelBinder(typeof(JsonModelBinder))] Delta productCategoryDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var category = _categoryApiService.GetCategoryById(productCategoryDelta.Dto.CategoryId.Value); - if (category == null) - { - return Error(HttpStatusCode.NotFound, "category_id", "not found"); - } - - var product = _productApiService.GetProductById(productCategoryDelta.Dto.ProductId.Value); - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product_id", "not found"); - } - - var mappingsCount = _productCategoryMappingsService.GetMappingsCount(product.Id, category.Id); - - if (mappingsCount > 0) - { - return Error(HttpStatusCode.BadRequest, "product_category_mapping", "already exist"); - } - - var newProductCategory = new ProductCategory(); - productCategoryDelta.Merge(newProductCategory); - - //inserting new category - _categoryService.InsertProductCategory(newProductCategory); - - // Preparing the result dto of the new product category mapping - var newProductCategoryMappingDto = newProductCategory.ToDto(); - - var productCategoryMappingsRootObject = new ProductCategoryMappingsRootObject(); - - productCategoryMappingsRootObject.ProductCategoryMappingDtos.Add(newProductCategoryMappingDto); - - var json = JsonFieldsSerializer.Serialize(productCategoryMappingsRootObject, string.Empty); - - //activity log - CustomerActivityService.InsertActivity("AddNewProductCategoryMapping", LocalizationService.GetResource("ActivityLog.AddNewProductCategoryMapping"), newProductCategory); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/product_category_mappings/{id}")] - [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - public IActionResult UpdateProductCategoryMapping([ModelBinder(typeof(JsonModelBinder))] Delta productCategoryDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - if (productCategoryDelta.Dto.CategoryId.HasValue) - { - var category = _categoryApiService.GetCategoryById(productCategoryDelta.Dto.CategoryId.Value); - if (category == null) - { - return Error(HttpStatusCode.NotFound, "category_id", "not found"); - } - } - - if (productCategoryDelta.Dto.ProductId.HasValue) - { - var product = _productApiService.GetProductById(productCategoryDelta.Dto.ProductId.Value); - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product_id", "not found"); - } - } - - // We do not need to validate the category id, because this will happen in the model binder using the dto validator. - var updateProductCategoryId = productCategoryDelta.Dto.Id; - - var productCategoryEntityToUpdate = _categoryService.GetProductCategoryById(updateProductCategoryId); - - if (productCategoryEntityToUpdate == null) - { - return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); - } - - productCategoryDelta.Merge(productCategoryEntityToUpdate); - - _categoryService.UpdateProductCategory(productCategoryEntityToUpdate); - - //activity log - CustomerActivityService.InsertActivity("UpdateProdutCategoryMapping", - LocalizationService.GetResource("ActivityLog.UpdateProdutCategoryMapping"), productCategoryEntityToUpdate); - - var updatedProductCategoryDto = productCategoryEntityToUpdate.ToDto(); - - var productCategoriesRootObject = new ProductCategoryMappingsRootObject(); - - productCategoriesRootObject.ProductCategoryMappingDtos.Add(updatedProductCategoryDto); - - var json = JsonFieldsSerializer.Serialize(productCategoriesRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/product_category_mappings/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteProductCategoryMapping(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var productCategory = _categoryService.GetProductCategoryById(id); - - if (productCategory == null) - { - return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); - } - - _categoryService.DeleteProductCategory(productCategory); - - //activity log - CustomerActivityService.InsertActivity("DeleteProductCategoryMapping", LocalizationService.GetResource("ActivityLog.DeleteProductCategoryMapping"), productCategory); - - return new RawJsonActionResult("{}"); - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.ProductCategoryMappings; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.ProductCategoryMappingsParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class ProductCategoryMappingsController : BaseApiController + { + private readonly IProductCategoryMappingsApiService _productCategoryMappingsService; + private readonly ICategoryService _categoryService; + private readonly ICategoryApiService _categoryApiService; + private readonly IProductApiService _productApiService; + + public ProductCategoryMappingsController(IProductCategoryMappingsApiService productCategoryMappingsService, + ICategoryService categoryService, + IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + ICategoryApiService categoryApiService, + IProductApiService productApiService, + IPictureService pictureService) + : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService,pictureService) + { + _productCategoryMappingsService = productCategoryMappingsService; + _categoryService = categoryService; + _categoryApiService = categoryApiService; + _productApiService = productApiService; + } + + /// + /// Receive a list of all Product-Category mappings + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/product_category_mappings")] + [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetMappings(ProductCategoryMappingsParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); + } + + IList mappingsAsDtos = + _productCategoryMappingsService.GetMappings(parameters.ProductId, + parameters.CategoryId, + parameters.Limit, + parameters.Page, + parameters.SinceId).Select(x => x.ToDto()).ToList(); + + var productCategoryMappingRootObject = new ProductCategoryMappingsRootObject() + { + ProductCategoryMappingDtos = mappingsAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(productCategoryMappingRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a count of all Product-Category mappings + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/product_category_mappings/count")] + [ProducesResponseType(typeof(ProductCategoryMappingsCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetMappingsCount(ProductCategoryMappingsCountParametersModel parameters) + { + if (parameters.ProductId < 0) + { + return Error(HttpStatusCode.BadRequest, "product_id", "invalid product_id"); + } + + if (parameters.CategoryId < 0) + { + return Error(HttpStatusCode.BadRequest, "category_id", "invalid category_id"); + } + + var mappingsCount = _productCategoryMappingsService.GetMappingsCount(parameters.ProductId, + parameters.CategoryId); + + var productCategoryMappingsCountRootObject = new ProductCategoryMappingsCountRootObject() + { + Count = mappingsCount + }; + + return Ok(productCategoryMappingsCountRootObject); + } + + /// + /// Retrieve Product-Category mappings by spcified id + /// + /// /// Id of the Product-Category mapping + /// Fields from the Product-Category mapping you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/product_category_mappings/{id}")] + [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetMappingById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var mapping = _productCategoryMappingsService.GetById(id); + + if (mapping == null) + { + return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); + } + + var productCategoryMappingsRootObject = new ProductCategoryMappingsRootObject(); + productCategoryMappingsRootObject.ProductCategoryMappingDtos.Add(mapping.ToDto()); + + var json = JsonFieldsSerializer.Serialize(productCategoryMappingsRootObject, fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/product_category_mappings")] + [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult CreateProductCategoryMapping([ModelBinder(typeof(JsonModelBinder))] Delta productCategoryDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var category = _categoryApiService.GetCategoryById(productCategoryDelta.Dto.CategoryId.Value); + if (category == null) + { + return Error(HttpStatusCode.NotFound, "category_id", "not found"); + } + + var product = _productApiService.GetProductById(productCategoryDelta.Dto.ProductId.Value); + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product_id", "not found"); + } + + var mappingsCount = _productCategoryMappingsService.GetMappingsCount(product.Id, category.Id); + + if (mappingsCount > 0) + { + return Error(HttpStatusCode.BadRequest, "product_category_mapping", "already exist"); + } + + var newProductCategory = new ProductCategory(); + productCategoryDelta.Merge(newProductCategory); + + //inserting new category + _categoryService.InsertProductCategory(newProductCategory); + + // Preparing the result dto of the new product category mapping + var newProductCategoryMappingDto = newProductCategory.ToDto(); + + var productCategoryMappingsRootObject = new ProductCategoryMappingsRootObject(); + + productCategoryMappingsRootObject.ProductCategoryMappingDtos.Add(newProductCategoryMappingDto); + + var json = JsonFieldsSerializer.Serialize(productCategoryMappingsRootObject, string.Empty); + + //activity log + CustomerActivityService.InsertActivity("AddNewProductCategoryMapping", LocalizationService.GetResource("ActivityLog.AddNewProductCategoryMapping"), newProductCategory); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/product_category_mappings/{id}")] + [ProducesResponseType(typeof(ProductCategoryMappingsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + public IActionResult UpdateProductCategoryMapping([ModelBinder(typeof(JsonModelBinder))] Delta productCategoryDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + if (productCategoryDelta.Dto.CategoryId.HasValue) + { + var category = _categoryApiService.GetCategoryById(productCategoryDelta.Dto.CategoryId.Value); + if (category == null) + { + return Error(HttpStatusCode.NotFound, "category_id", "not found"); + } + } + + if (productCategoryDelta.Dto.ProductId.HasValue) + { + var product = _productApiService.GetProductById(productCategoryDelta.Dto.ProductId.Value); + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product_id", "not found"); + } + } + + // We do not need to validate the category id, because this will happen in the model binder using the dto validator. + var updateProductCategoryId = productCategoryDelta.Dto.Id; + + var productCategoryEntityToUpdate = _categoryService.GetProductCategoryById(updateProductCategoryId); + + if (productCategoryEntityToUpdate == null) + { + return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); + } + + productCategoryDelta.Merge(productCategoryEntityToUpdate); + + _categoryService.UpdateProductCategory(productCategoryEntityToUpdate); + + //activity log + CustomerActivityService.InsertActivity("UpdateProdutCategoryMapping", LocalizationService.GetResource("ActivityLog.UpdateProdutCategoryMapping"), productCategoryEntityToUpdate); + + var updatedProductCategoryDto = productCategoryEntityToUpdate.ToDto(); + + var productCategoriesRootObject = new ProductCategoryMappingsRootObject(); + + productCategoriesRootObject.ProductCategoryMappingDtos.Add(updatedProductCategoryDto); + + var json = JsonFieldsSerializer.Serialize(productCategoriesRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/product_category_mappings/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteProductCategoryMapping(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var productCategory = _categoryService.GetProductCategoryById(id); + + if (productCategory == null) + { + return Error(HttpStatusCode.NotFound, "product_category_mapping", "not found"); + } + + _categoryService.DeleteProductCategory(productCategory); + + //activity log + CustomerActivityService.InsertActivity("DeleteProductCategoryMapping", LocalizationService.GetResource("ActivityLog.DeleteProductCategoryMapping"), productCategory); + + return new RawJsonActionResult("{}"); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/ProductManufacturerMappingsController.cs b/Controllers/ProductManufacturerMappingsController.cs similarity index 97% rename from Nop.Plugin.Api/Controllers/ProductManufacturerMappingsController.cs rename to Controllers/ProductManufacturerMappingsController.cs index 9af0b75..66e5240 100644 --- a/Nop.Plugin.Api/Controllers/ProductManufacturerMappingsController.cs +++ b/Controllers/ProductManufacturerMappingsController.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; +using Microsoft.AspNetCore.Mvc; using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.ProductManufacturerMappings; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.ProductManufacturerMappings; using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; using Nop.Plugin.Api.MappingExtensions; using Nop.Plugin.Api.ModelBinders; using Nop.Plugin.Api.Models.ProductManufacturerMappingsParameters; @@ -19,15 +18,14 @@ using Nop.Services.Media; using Nop.Services.Security; using Nop.Services.Stores; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Controllers { - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class ProductManufacturerMappingsController : BaseApiController { private readonly IProductManufacturerMappingsApiService _productManufacturerMappingsService; diff --git a/Controllers/ProductPicturesController.cs b/Controllers/ProductPicturesController.cs new file mode 100644 index 0000000..1f71c63 --- /dev/null +++ b/Controllers/ProductPicturesController.cs @@ -0,0 +1,172 @@ +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.ProductImages; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using System; +using System.Net; + +namespace Nop.Plugin.Api.Controllers +{ + public class ProductPicturesController : BaseApiController + { + private readonly IProductService _productService; + private readonly IDTOHelper _dtoHelper; + + //private readonly IFactory _factory; + + public ProductPicturesController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService, + IProductService productService, + IDTOHelper dtoHelper) : + base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _productService = productService; + _dtoHelper = dtoHelper; + } + + [HttpPut] + [Route("/api/productpictures/{id}")] + [ProducesResponseType(typeof(ProductPicturesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult UpdateProductPicture([ModelBinder(typeof(JsonModelBinder))] Delta productPictureDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + throw new NotImplementedException("Update is not yet implemented."); + + /* + Because there appears to be a bug in the PictureService.UpdatePicture method (where the thumbnail images aren't replaced) we have not implemented this method. + The below code *should* work but it doesn't because it appears that the thumbnail images arent being updated in the thumbnail store. + Leaving the code here so that it might be addressed at some point. + */ + + + //var product = _productService.GetProductById(productPictureDelta.Dto.ProductId); + //var picture = PictureService.GetPictureById(productPictureDelta.Dto.Id); + + //var updatedPicture = PictureService.UpdatePicture(picture.Id, productPictureDelta.Dto.Binary, productPictureDelta.Dto.MimeType, productPictureDelta.Dto.SeoFilename); + //PictureService.SetSeoFilename(picture.Id, PictureService.GetPictureSeName(product.Name)); + + //var productPicture = _productService.GetProductPictureById(productPictureDelta.Dto.Id); + //productPicture.DisplayOrder = productPictureDelta.Dto.Position; + + //_productService.UpdateProductPicture(productPicture); + + //var productImagesRootObject = new ProductPicturesRootObjectDto(); + //productImagesRootObject.Image = _dtoHelper.PrepareProductPictureDTO(productPicture); + + //var json = JsonFieldsSerializer.Serialize(productImagesRootObject, string.Empty); + + //return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/productpictures")] + [ProducesResponseType(typeof(ProductPicturesRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult CreateProductPicture([ModelBinder(typeof(JsonModelBinder))] Delta productPictureDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + CustomerActivityService.InsertActivity("APIService", string.Format("Attempting to create picture with name {0}.", productPictureDelta.Dto.SeoFilename), null); + + var newPicture = PictureService.InsertPicture(Convert.FromBase64String(productPictureDelta.Dto.Attachment), productPictureDelta.Dto.MimeType, productPictureDelta.Dto.SeoFilename); + + var productPicture = new ProductPicture() + { + PictureId = newPicture.Id, + ProductId = productPictureDelta.Dto.ProductId, + DisplayOrder = productPictureDelta.Dto.Position + }; + + _productService.InsertProductPicture(productPicture); + + var product = _productService.GetProductById(productPictureDelta.Dto.ProductId); + PictureService.SetSeoFilename(newPicture.Id, PictureService.GetPictureSeName(product.Name)); + + var productImagesRootObject = new ProductPicturesRootObjectDto(); + productImagesRootObject.Image = _dtoHelper.PrepareProductPictureDTO(productPicture); + + var json = JsonFieldsSerializer.Serialize(productImagesRootObject, string.Empty); + + CustomerActivityService.InsertActivity("APIService", string.Format("Successfully created and returned image {0}.", productPictureDelta.Dto.SeoFilename), null); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/productpictures/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeletePicture(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + CustomerActivityService.InsertActivity("APIService", string.Format("Attempting delete of picture {0}.", id), null); + + var productPicture = _productService.GetProductPictureById(id); + if (productPicture == null) + return Error(HttpStatusCode.NotFound, "product picture", "not found"); + + var picture = PictureService.GetPictureById(productPicture.PictureId); + if (picture == null) + return Error(HttpStatusCode.NotFound, "picture", "not found"); + + + _productService.DeleteProductPicture(productPicture); + PictureService.DeletePicture(picture); + + + CustomerActivityService.InsertActivity("APIService", string.Format("Deleted picture {0}.", picture.Id), picture); + + return new RawJsonActionResult("{}"); + } + + } +} diff --git a/Nop.Plugin.Api/Controllers/ProductSpecificationAttributesController.cs b/Controllers/ProductSpecificationAttributesController.cs similarity index 97% rename from Nop.Plugin.Api/Controllers/ProductSpecificationAttributesController.cs rename to Controllers/ProductSpecificationAttributesController.cs index f122135..f0b3d0b 100644 --- a/Nop.Plugin.Api/Controllers/ProductSpecificationAttributesController.cs +++ b/Controllers/ProductSpecificationAttributesController.cs @@ -1,11 +1,9 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.SpecificationAttributes; using Nop.Plugin.Api.Helpers; using Nop.Plugin.Api.JSON.ActionResults; using Nop.Plugin.Api.JSON.Serializers; @@ -22,10 +20,10 @@ using Nop.Services.Stores; using System.Linq; using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Controllers { - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class ProductSpecificationAttributesController : BaseApiController { private readonly ISpecificationAttributeService _specificationAttributeService; diff --git a/Nop.Plugin.Api/Controllers/ProductsController.cs b/Controllers/ProductsController.cs similarity index 82% rename from Nop.Plugin.Api/Controllers/ProductsController.cs rename to Controllers/ProductsController.cs index 8b1914e..9ac16fa 100644 --- a/Nop.Plugin.Api/Controllers/ProductsController.cs +++ b/Controllers/ProductsController.cs @@ -1,609 +1,642 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Discounts; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Products; -using Nop.Plugin.Api.Factories; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.ProductsParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Seo; -using Nop.Services.Stores; -using Nop.Plugin.Api.Helpers; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class ProductsController : BaseApiController - { - private readonly IProductApiService _productApiService; - private readonly IProductService _productService; - private readonly IUrlRecordService _urlRecordService; - private readonly IManufacturerService _manufacturerService; - private readonly IFactory _factory; - private readonly IProductTagService _productTagService; - private readonly IProductAttributeService _productAttributeService; - private readonly IDTOHelper _dtoHelper; - - public ProductsController(IProductApiService productApiService, - IJsonFieldsSerializer jsonFieldsSerializer, - IProductService productService, - IUrlRecordService urlRecordService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IFactory factory, - IAclService aclService, - IStoreMappingService storeMappingService, - IStoreService storeService, - ICustomerService customerService, - IDiscountService discountService, - IPictureService pictureService, - IManufacturerService manufacturerService, - IProductTagService productTagService, - IProductAttributeService productAttributeService, - IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) - { - _productApiService = productApiService; - _factory = factory; - _manufacturerService = manufacturerService; - _productTagService = productTagService; - _urlRecordService = urlRecordService; - _productService = productService; - _productAttributeService = productAttributeService; - _dtoHelper = dtoHelper; - } - - /// - /// Receive a list of all products - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/products")] - [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProducts(ProductsParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); - } - - var allProducts = _productApiService.GetProducts(parameters.Ids, parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.UpdatedAtMin, - parameters.UpdatedAtMax, parameters.Limit, parameters.Page, parameters.SinceId, parameters.CategoryId, - parameters.VendorName, parameters.PublishedStatus) - .Where(p => StoreMappingService.Authorize(p)); - - IList productsAsDtos = allProducts.Select(product => _dtoHelper.PrepareProductDTO(product)).ToList(); - - var productsRootObject = new ProductsRootObjectDto() - { - Products = productsAsDtos - }; - - var json = JsonFieldsSerializer.Serialize(productsRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a count of all products - /// - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/products/count")] - [ProducesResponseType(typeof(ProductsCountRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProductsCount(ProductsCountParametersModel parameters) - { - var allProductsCount = _productApiService.GetProductsCount(parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.UpdatedAtMin, - parameters.UpdatedAtMax, parameters.PublishedStatus, parameters.VendorName, - parameters.CategoryId); - - var productsCountRootObject = new ProductsCountRootObject() - { - Count = allProductsCount - }; - - return Ok(productsCountRootObject); - } - - /// - /// Retrieve product by spcified id - /// - /// Id of the product - /// Fields from the product you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/products/{id}")] - [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetProductById(int id, string fields = "") - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var product = _productApiService.GetProductById(id); - - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product", "not found"); - } - - var productDto = _dtoHelper.PrepareProductDTO(product); - - var productsRootObject = new ProductsRootObjectDto(); - - productsRootObject.Products.Add(productDto); - - var json = JsonFieldsSerializer.Serialize(productsRootObject, fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/products")] - [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - public IActionResult CreateProduct([ModelBinder(typeof(JsonModelBinder))] Delta productDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - // Inserting the new product - var product = _factory.Initialize(); - productDelta.Merge(product); - - _productService.InsertProduct(product); - - UpdateProductPictures(product, productDelta.Dto.Images); - - UpdateProductTags(product, productDelta.Dto.Tags); - - UpdateProductManufacturers(product, productDelta.Dto.ManufacturerIds); - - UpdateAssociatedProducts(product, productDelta.Dto.AssociatedProductIds); - - //search engine name - var seName = _urlRecordService.ValidateSeName(product, productDelta.Dto.SeName, product.Name, true); - _urlRecordService.SaveSlug(product, seName, 0); - - UpdateAclRoles(product, productDelta.Dto.RoleIds); - - UpdateDiscountMappings(product, productDelta.Dto.DiscountIds); - - UpdateStoreMappings(product, productDelta.Dto.StoreIds); - - _productService.UpdateProduct(product); - - CustomerActivityService.InsertActivity("AddNewProduct", - LocalizationService.GetResource("ActivityLog.AddNewProduct"), product); - - // Preparing the result dto of the new product - var productDto = _dtoHelper.PrepareProductDTO(product); - - var productsRootObject = new ProductsRootObjectDto(); - - productsRootObject.Products.Add(productDto); - - var json = JsonFieldsSerializer.Serialize(productsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/products/{id}")] - [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - public IActionResult UpdateProduct([ModelBinder(typeof(JsonModelBinder))] Delta productDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var product = _productApiService.GetProductById(productDelta.Dto.Id); - - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product", "not found"); - } - - productDelta.Merge(product); - - product.UpdatedOnUtc = DateTime.UtcNow; - _productService.UpdateProduct(product); - - UpdateProductAttributes(product, productDelta); - - UpdateProductPictures(product, productDelta.Dto.Images); - - UpdateProductTags(product, productDelta.Dto.Tags); - - UpdateProductManufacturers(product, productDelta.Dto.ManufacturerIds); - - UpdateAssociatedProducts(product, productDelta.Dto.AssociatedProductIds); - - // Update the SeName if specified - if (productDelta.Dto.SeName != null) - { - var seName = _urlRecordService.ValidateSeName(product, productDelta.Dto.SeName, product.Name, true); - _urlRecordService.SaveSlug(product, seName, 0); - } - - UpdateDiscountMappings(product, productDelta.Dto.DiscountIds); - - UpdateStoreMappings(product, productDelta.Dto.StoreIds); - - UpdateAclRoles(product, productDelta.Dto.RoleIds); - - _productService.UpdateProduct(product); - - CustomerActivityService.InsertActivity("UpdateProduct", - LocalizationService.GetResource("ActivityLog.UpdateProduct"), product); - - // Preparing the result dto of the new product - var productDto = _dtoHelper.PrepareProductDTO(product); - - var productsRootObject = new ProductsRootObjectDto(); - - productsRootObject.Products.Add(productDto); - - var json = JsonFieldsSerializer.Serialize(productsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/products/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteProduct(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var product = _productApiService.GetProductById(id); - - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product", "not found"); - } - - _productService.DeleteProduct(product); - - //activity log - CustomerActivityService.InsertActivity("DeleteProduct", - string.Format(LocalizationService.GetResource("ActivityLog.DeleteProduct"), product.Name), product); - - return new RawJsonActionResult("{}"); - } - - private void UpdateProductPictures(Product entityToUpdate, List setPictures) - { - // If no pictures are specified means we don't have to update anything - if (setPictures == null) - return; - - // delete unused product pictures - var unusedProductPictures = entityToUpdate.ProductPictures.Where(x => setPictures.All(y => y.Id != x.Id)).ToList(); - foreach (var unusedProductPicture in unusedProductPictures) - { - var picture = PictureService.GetPictureById(unusedProductPicture.PictureId); - if (picture == null) - throw new ArgumentException("No picture found with the specified id"); - PictureService.DeletePicture(picture); - } - - foreach (var imageDto in setPictures) - { - if (imageDto.Id > 0) - { - // update existing product picture - var productPictureToUpdate = entityToUpdate.ProductPictures.FirstOrDefault(x => x.Id == imageDto.Id); - if (productPictureToUpdate != null && imageDto.Position > 0) - { - productPictureToUpdate.DisplayOrder = imageDto.Position; - _productService.UpdateProductPicture(productPictureToUpdate); - } - } - else - { - // add new product picture - var newPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); - _productService.InsertProductPicture(new ProductPicture() - { - PictureId = newPicture.Id, - ProductId = entityToUpdate.Id, - DisplayOrder = imageDto.Position - }); - } - } - } - - private void UpdateProductAttributes(Product entityToUpdate, Delta productDtoDelta) - { - // If no product attribute mappings are specified means we don't have to update anything - if (productDtoDelta.Dto.ProductAttributeMappings == null) - return; - - // delete unused product attribute mappings - var toBeUpdatedIds = productDtoDelta.Dto.ProductAttributeMappings.Where(y => y.Id != 0).Select(x => x.Id); - - var unusedProductAttributeMappings = entityToUpdate.ProductAttributeMappings.Where(x => !toBeUpdatedIds.Contains(x.Id)).ToList(); - - foreach (var unusedProductAttributeMapping in unusedProductAttributeMappings) - { - _productAttributeService.DeleteProductAttributeMapping(unusedProductAttributeMapping); - } - - foreach (var productAttributeMappingDto in productDtoDelta.Dto.ProductAttributeMappings) - { - if (productAttributeMappingDto.Id > 0) - { - // update existing product attribute mapping - var productAttributeMappingToUpdate = entityToUpdate.ProductAttributeMappings.FirstOrDefault(x => x.Id == productAttributeMappingDto.Id); - if (productAttributeMappingToUpdate != null) - { - productDtoDelta.Merge(productAttributeMappingDto,productAttributeMappingToUpdate,false); - - _productAttributeService.UpdateProductAttributeMapping(productAttributeMappingToUpdate); - - UpdateProductAttributeValues(productAttributeMappingDto, productDtoDelta); - } - } - else - { - var newProductAttributeMapping = new ProductAttributeMapping {ProductId = entityToUpdate.Id}; - - productDtoDelta.Merge(productAttributeMappingDto, newProductAttributeMapping); - - // add new product attribute - _productAttributeService.InsertProductAttributeMapping(newProductAttributeMapping); - } - } - } - - private void UpdateProductAttributeValues(ProductAttributeMappingDto productAttributeMappingDto, Delta productDtoDelta) - { - // If no product attribute values are specified means we don't have to update anything - if (productAttributeMappingDto.ProductAttributeValues == null) - return; - - // delete unused product attribute values - var toBeUpdatedIds = productAttributeMappingDto.ProductAttributeValues.Where(y => y.Id != 0).Select(x => x.Id); - - var unusedProductAttributeValues = - _productAttributeService.GetProductAttributeValues(productAttributeMappingDto.Id).Where(x => !toBeUpdatedIds.Contains(x.Id)).ToList(); - - foreach (var unusedProductAttributeValue in unusedProductAttributeValues) - { - _productAttributeService.DeleteProductAttributeValue(unusedProductAttributeValue); - } - - foreach (var productAttributeValueDto in productAttributeMappingDto.ProductAttributeValues) - { - if (productAttributeValueDto.Id > 0) - { - // update existing product attribute mapping - var productAttributeValueToUpdate = - _productAttributeService.GetProductAttributeValueById(productAttributeValueDto.Id); - if (productAttributeValueToUpdate != null) - { - productDtoDelta.Merge(productAttributeValueDto, productAttributeValueToUpdate, false); - - _productAttributeService.UpdateProductAttributeValue(productAttributeValueToUpdate); - } - } - else - { - var newProductAttributeValue = new ProductAttributeValue(); - productDtoDelta.Merge(productAttributeValueDto, newProductAttributeValue); - - newProductAttributeValue.ProductAttributeMappingId = productAttributeMappingDto.Id; - // add new product attribute value - _productAttributeService.InsertProductAttributeValue(newProductAttributeValue); - } - } - } - - private void UpdateProductTags(Product product, IReadOnlyCollection productTags) - { - if (productTags == null) - return; - - if (product == null) - throw new ArgumentNullException(nameof(product)); - - //Copied from UpdateProductTags method of ProductTagService - //product tags - var existingProductTags = _productTagService.GetAllProductTagsByProductId(product.Id); - var productTagsToRemove = new List(); - foreach (var existingProductTag in existingProductTags) - { - var found = false; - foreach (var newProductTag in productTags) - { - if (!existingProductTag.Name.Equals(newProductTag, StringComparison.InvariantCultureIgnoreCase)) - continue; - - found = true; - break; - } - - if (!found) - { - productTagsToRemove.Add(existingProductTag); - } - } - - foreach (var productTag in productTagsToRemove) - { - //product.ProductTags.Remove(productTag); - product.ProductProductTagMappings - .Remove(product.ProductProductTagMappings.FirstOrDefault(mapping => mapping.ProductTagId == productTag.Id)); - _productService.UpdateProduct(product); - } - - foreach (var productTagName in productTags) - { - ProductTag productTag; - var productTag2 = _productTagService.GetProductTagByName(productTagName); - if (productTag2 == null) - { - //add new product tag - productTag = new ProductTag - { - Name = productTagName - }; - _productTagService.InsertProductTag(productTag); - } - else - { - productTag = productTag2; - } - - if (!_productService.ProductTagExists(product, productTag.Id)) - { - product.ProductProductTagMappings.Add(new ProductProductTagMapping { ProductTag = productTag }); - _productService.UpdateProduct(product); - } - - var seName = _urlRecordService.ValidateSeName(productTag, string.Empty, productTag.Name, true); - _urlRecordService.SaveSlug(productTag, seName, 0); - } - } - - private void UpdateDiscountMappings(Product product, List passedDiscountIds) - { - if (passedDiscountIds == null) - return; - - var allDiscounts = DiscountService.GetAllDiscounts(DiscountType.AssignedToSkus, showHidden: true); - - foreach (var discount in allDiscounts) - { - if (passedDiscountIds.Contains(discount.Id)) - { - //new discount - if (product.AppliedDiscounts.Count(d => d.Id == discount.Id) == 0) - product.AppliedDiscounts.Add(discount); - } - else - { - //remove discount - if (product.AppliedDiscounts.Count(d => d.Id == discount.Id) > 0) - product.AppliedDiscounts.Remove(discount); - } - } - - _productService.UpdateProduct(product); - _productService.UpdateHasDiscountsApplied(product); - } - - private void UpdateProductManufacturers(Product product, List passedManufacturerIds) - { - // If no manufacturers specified then there is nothing to map - if (passedManufacturerIds == null) - return; - - var unusedProductManufacturers = product.ProductManufacturers.Where(x => !passedManufacturerIds.Contains(x.ManufacturerId)).ToList(); - - // remove all manufacturers that are not passed - foreach (var unusedProductManufacturer in unusedProductManufacturers) - { - _manufacturerService.DeleteProductManufacturer(unusedProductManufacturer); - } - - foreach (var passedManufacturerId in passedManufacturerIds) - { - // not part of existing manufacturers so we will create a new one - if (product.ProductManufacturers.All(x => x.ManufacturerId != passedManufacturerId)) - { - // if manufacturer does not exist we simply ignore it, otherwise add it to the product - var manufacturer = _manufacturerService.GetManufacturerById(passedManufacturerId); - if (manufacturer != null) - { - _manufacturerService.InsertProductManufacturer(new ProductManufacturer() - { ProductId = product.Id, ManufacturerId = manufacturer.Id }); - } - } - } - } - - private void UpdateAssociatedProducts(Product product, List passedAssociatedProductIds) - { - // If no associated products specified then there is nothing to map - if (passedAssociatedProductIds == null) - return; - - var noLongerAssociatedProducts = - _productService.GetAssociatedProducts(product.Id, showHidden: true) - .Where(p => !passedAssociatedProductIds.Contains(p.Id)); - - // update all products that are no longer associated with our product - foreach (var noLongerAssocuatedProduct in noLongerAssociatedProducts) - { - noLongerAssocuatedProduct.ParentGroupedProductId = 0; - _productService.UpdateProduct(noLongerAssocuatedProduct); - } - - var newAssociatedProducts = _productService.GetProductsByIds(passedAssociatedProductIds.ToArray()); - foreach (var newAssociatedProduct in newAssociatedProducts) - { - newAssociatedProduct.ParentGroupedProductId = product.Id; - _productService.UpdateProduct(newAssociatedProduct); - } - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Discounts; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.ProductsParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Seo; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class ProductsController : BaseApiController + { + private readonly IProductApiService _productApiService; + private readonly IProductService _productService; + private readonly IUrlRecordService _urlRecordService; + private readonly IManufacturerService _manufacturerService; + private readonly IFactory _factory; + private readonly IProductTagService _productTagService; + private readonly IProductAttributeService _productAttributeService; + private readonly IDTOHelper _dtoHelper; + private readonly ILogger _logger; + + public ProductsController(IProductApiService productApiService, + IJsonFieldsSerializer jsonFieldsSerializer, + IProductService productService, + IUrlRecordService urlRecordService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IFactory factory, + IAclService aclService, + IStoreMappingService storeMappingService, + IStoreService storeService, + ICustomerService customerService, + IDiscountService discountService, + IPictureService pictureService, + IManufacturerService manufacturerService, + IProductTagService productTagService, + IProductAttributeService productAttributeService, + ILogger logger, + IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) + { + _productApiService = productApiService; + _factory = factory; + _manufacturerService = manufacturerService; + _productTagService = productTagService; + _urlRecordService = urlRecordService; + _productService = productService; + _productAttributeService = productAttributeService; + _logger = logger; + _dtoHelper = dtoHelper; + } + + /// + /// Receive a list of all products + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/products")] + [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProducts(ProductsParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); + } + + var allProducts = _productApiService.GetProducts(parameters.Ids, parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.UpdatedAtMin, + parameters.UpdatedAtMax, parameters.Limit, parameters.Page, parameters.SinceId, parameters.CategoryId, + parameters.VendorName, parameters.PublishedStatus) + .Where(p => StoreMappingService.Authorize(p)); + + IList productsAsDtos = allProducts.Select(product => _dtoHelper.PrepareProductDTO(product)).ToList(); + + var productsRootObject = new ProductsRootObjectDto() + { + Products = productsAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(productsRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a count of all products + /// + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/products/count")] + [ProducesResponseType(typeof(ProductsCountRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProductsCount(ProductsCountParametersModel parameters) + { + var allProductsCount = _productApiService.GetProductsCount(parameters.CreatedAtMin, parameters.CreatedAtMax, parameters.UpdatedAtMin, + parameters.UpdatedAtMax, parameters.PublishedStatus, parameters.VendorName, + parameters.CategoryId); + + var productsCountRootObject = new ProductsCountRootObject() + { + Count = allProductsCount + }; + + return Ok(productsCountRootObject); + } + + /// + /// Retrieve product by spcified id + /// + /// Id of the product + /// Fields from the product you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/products/{id}")] + [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetProductById(int id, string fields = "") + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var product = _productApiService.GetProductById(id); + + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product", "not found"); + } + + var productDto = _dtoHelper.PrepareProductDTO(product); + + var productsRootObject = new ProductsRootObjectDto(); + + productsRootObject.Products.Add(productDto); + + var json = JsonFieldsSerializer.Serialize(productsRootObject, fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/products")] + [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult CreateProduct([ModelBinder(typeof(JsonModelBinder))] Delta productDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + CustomerActivityService.InsertActivity("APIService", "Starting Product Create", null); + + // Inserting the new product + var product = _factory.Initialize(); + productDelta.Merge(product); + + _productService.InsertProduct(product); + + UpdateProductPictures(product, productDelta.Dto.Images); + + UpdateProductTags(product, productDelta.Dto.Tags); + + UpdateProductManufacturers(product, productDelta.Dto.ManufacturerIds); + + UpdateAssociatedProducts(product, productDelta.Dto.AssociatedProductIds); + + //search engine name + var seName = _urlRecordService.ValidateSeName(product, productDelta.Dto.SeName, product.Name, true); + _urlRecordService.SaveSlug(product, seName, 0); + + UpdateAclRoles(product, productDelta.Dto.RoleIds); + + UpdateDiscountMappings(product, productDelta.Dto.DiscountIds); + + UpdateStoreMappings(product, productDelta.Dto.StoreIds); + + _productService.UpdateProduct(product); + + CustomerActivityService.InsertActivity("APIService", LocalizationService.GetResource("ActivityLog.AddNewProduct"), product); + + // Preparing the result dto of the new product + var productDto = _dtoHelper.PrepareProductDTO(product); + + var productsRootObject = new ProductsRootObjectDto(); + + productsRootObject.Products.Add(productDto); + + var json = JsonFieldsSerializer.Serialize(productsRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpPut] + [Route("/api/products/{id}")] + [ProducesResponseType(typeof(ProductsRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + public IActionResult UpdateProduct([ModelBinder(typeof(JsonModelBinder))] Delta productDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + CustomerActivityService.InsertActivity("APIService", "Starting Product Update", null); + + var product = _productApiService.GetProductById(productDelta.Dto.Id); + + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product", "not found"); + } + + productDelta.Merge(product); + + product.UpdatedOnUtc = DateTime.UtcNow; + _productService.UpdateProduct(product); + + UpdateProductAttributes(product, productDelta); + + UpdateProductPictures(product, productDelta.Dto.Images); + + UpdateProductTags(product, productDelta.Dto.Tags); + + UpdateProductManufacturers(product, productDelta.Dto.ManufacturerIds); + + UpdateAssociatedProducts(product, productDelta.Dto.AssociatedProductIds); + + // Update the SeName if specified + if (productDelta.Dto.SeName != null) + { + var seName = _urlRecordService.ValidateSeName(product, productDelta.Dto.SeName, product.Name, true); + _urlRecordService.SaveSlug(product, seName, 0); + } + + UpdateDiscountMappings(product, productDelta.Dto.DiscountIds); + + UpdateStoreMappings(product, productDelta.Dto.StoreIds); + + UpdateAclRoles(product, productDelta.Dto.RoleIds); + + _productService.UpdateProduct(product); + + CustomerActivityService.InsertActivity("APIService", LocalizationService.GetResource("ActivityLog.UpdateProduct"), product); + + // Preparing the result dto of the new product + var productDto = _dtoHelper.PrepareProductDTO(product); + + var productsRootObject = new ProductsRootObjectDto(); + + productsRootObject.Products.Add(productDto); + + var json = JsonFieldsSerializer.Serialize(productsRootObject, string.Empty); + + return new RawJsonActionResult(json); + + + } + + [HttpDelete] + [Route("/api/products/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteProduct(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var product = _productApiService.GetProductById(id); + + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product", "not found"); + } + + _productService.DeleteProduct(product); + + //activity log + CustomerActivityService.InsertActivity("APIService", string.Format(LocalizationService.GetResource("ActivityLog.DeleteProduct"), product.Name), product); + + return new RawJsonActionResult("{}"); + } + + private void UpdateProductPictures(Product entityToUpdate, List setPictures) + { + // If no pictures are specified means we don't have to update anything + if (setPictures == null) + { + return; + } + + // delete unused product pictures + var productPictures = _productService.GetProductPicturesByProductId(entityToUpdate.Id); + var unusedProductPictures = productPictures.Where(x => setPictures.All(y => y.Id != x.Id)).ToList(); + foreach (var unusedProductPicture in unusedProductPictures) + { + var picture = PictureService.GetPictureById(unusedProductPicture.PictureId); + if (picture == null) + { + throw new ArgumentException("No picture found with the specified id"); + } + PictureService.DeletePicture(picture); + } + + foreach (var imageDto in setPictures) + { + if (imageDto.Id > 0) + { + // update existing product picture + var productPictureToUpdate = productPictures.FirstOrDefault(x => x.Id == imageDto.Id); + if (productPictureToUpdate != null && imageDto.Position > 0) + { + productPictureToUpdate.DisplayOrder = imageDto.Position; + _productService.UpdateProductPicture(productPictureToUpdate); + } + } + else + { + // add new product picture + var newPicture = PictureService.InsertPicture(imageDto.Binary, imageDto.MimeType, string.Empty); + _productService.InsertProductPicture(new ProductPicture + { + PictureId = newPicture.Id, + ProductId = entityToUpdate.Id, + DisplayOrder = imageDto.Position + }); + } + } + } + private void UpdateProductAttributes(Product entityToUpdate, Delta productDtoDelta) + { + // If no product attribute mappings are specified means we don't have to update anything + if (productDtoDelta.Dto.ProductAttributeMappings == null) + { + return; + } + + // delete unused product attribute mappings + var toBeUpdatedIds = productDtoDelta.Dto.ProductAttributeMappings.Where(y => y.Id != 0).Select(x => x.Id); + var productAttributeMappings = _productAttributeService.GetProductAttributeMappingsByProductId(entityToUpdate.Id); + var unusedProductAttributeMappings = productAttributeMappings.Where(x => !toBeUpdatedIds.Contains(x.Id)).ToList(); + + foreach (var unusedProductAttributeMapping in unusedProductAttributeMappings) + { + _productAttributeService.DeleteProductAttributeMapping(unusedProductAttributeMapping); + } + + foreach (var productAttributeMappingDto in productDtoDelta.Dto.ProductAttributeMappings) + { + if (productAttributeMappingDto.Id > 0) + { + // update existing product attribute mapping + var productAttributeMappingToUpdate = productAttributeMappings.FirstOrDefault(x => x.Id == productAttributeMappingDto.Id); + if (productAttributeMappingToUpdate != null) + { + productDtoDelta.Merge(productAttributeMappingDto, productAttributeMappingToUpdate, false); + + _productAttributeService.UpdateProductAttributeMapping(productAttributeMappingToUpdate); + + UpdateProductAttributeValues(productAttributeMappingDto, productDtoDelta); + } + } + else + { + var newProductAttributeMapping = new ProductAttributeMapping + { + ProductId = entityToUpdate.Id + }; + + productDtoDelta.Merge(productAttributeMappingDto, newProductAttributeMapping); + + // add new product attribute + _productAttributeService.InsertProductAttributeMapping(newProductAttributeMapping); + } + } + } + + private void UpdateProductAttributeValues(ProductAttributeMappingDto productAttributeMappingDto, Delta productDtoDelta) + { + // If no product attribute values are specified means we don't have to update anything + if (productAttributeMappingDto.ProductAttributeValues == null) + return; + + // delete unused product attribute values + var toBeUpdatedIds = productAttributeMappingDto.ProductAttributeValues.Where(y => y.Id != 0).Select(x => x.Id); + + var unusedProductAttributeValues = + _productAttributeService.GetProductAttributeValues(productAttributeMappingDto.Id).Where(x => !toBeUpdatedIds.Contains(x.Id)).ToList(); + + foreach (var unusedProductAttributeValue in unusedProductAttributeValues) + { + _productAttributeService.DeleteProductAttributeValue(unusedProductAttributeValue); + } + + foreach (var productAttributeValueDto in productAttributeMappingDto.ProductAttributeValues) + { + if (productAttributeValueDto.Id > 0) + { + // update existing product attribute mapping + var productAttributeValueToUpdate = + _productAttributeService.GetProductAttributeValueById(productAttributeValueDto.Id); + if (productAttributeValueToUpdate != null) + { + productDtoDelta.Merge(productAttributeValueDto, productAttributeValueToUpdate, false); + + _productAttributeService.UpdateProductAttributeValue(productAttributeValueToUpdate); + } + } + else + { + var newProductAttributeValue = new ProductAttributeValue(); + productDtoDelta.Merge(productAttributeValueDto, newProductAttributeValue); + + newProductAttributeValue.ProductAttributeMappingId = productAttributeMappingDto.Id; + // add new product attribute value + _productAttributeService.InsertProductAttributeValue(newProductAttributeValue); + } + } + } + + private void UpdateProductTags(Product product, IReadOnlyCollection productTags) + { + if (productTags == null) + { + return; + } + + if (product == null) + { + throw new ArgumentNullException(nameof(product)); + } + + var existingProductTags = _productTagService.GetAllProductTagsByProductId(product.Id); + var productTagsToRemove = new List(); + foreach (var existingProductTag in existingProductTags) + { + var found = false; + foreach (var newProductTag in productTags) + { + if (!existingProductTag.Name.Equals(newProductTag, StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + found = true; + break; + } + + if (!found) + { + productTagsToRemove.Add(existingProductTag); + } + } + + try + { + this._productTagService.UpdateProductTags(product, productTagsToRemove.Select(o => o.Name).ToArray()); + + foreach (var productTagName in productTags) + { + ProductTag productTag; + var productTag2 = _productTagService.GetProductTagByName(productTagName); + if (productTag2 == null) + { + //add new product tag + productTag = new ProductTag + { + Name = productTagName + }; + _productTagService.InsertProductTag(productTag); + } + else + { + productTag = productTag2; + } + + var seName = _urlRecordService.ValidateSeName(productTag, string.Empty, productTag.Name, true); + _urlRecordService.SaveSlug(productTag, seName, 0); + + //Perform a final check to deal with duplicates etc. + var currentProductTags = _productTagService.GetAllProductTagsByProductId(product.Id); + if (!currentProductTags.Any(o => o.Id == productTag.Id)) + { + _productTagService.InsertProductProductTagMapping(new ProductProductTagMapping() + { + ProductId = product.Id, + ProductTagId = productTag.Id + }); + } + + } + } + catch (Exception ex) + { + throw; + } + } + private void UpdateDiscountMappings(Product product, List passedDiscountIds) + { + if (passedDiscountIds == null) + { + return; + } + + var allDiscounts = DiscountService.GetAllDiscounts(DiscountType.AssignedToSkus, showHidden: true); + var appliedProductDiscount = DiscountService.GetAppliedDiscounts(product); + foreach (var discount in allDiscounts) + { + if (passedDiscountIds.Contains(discount.Id)) + { + //new discount + if (appliedProductDiscount.Count(d => d.Id == discount.Id) == 0) + { + appliedProductDiscount.Add(discount); + } + } + else + { + //remove discount + if (appliedProductDiscount.Count(d => d.Id == discount.Id) > 0) + { + appliedProductDiscount.Remove(discount); + } + } + } + + _productService.UpdateProduct(product); + _productService.UpdateHasDiscountsApplied(product); + } + + + + private void UpdateProductManufacturers(Product product, List passedManufacturerIds) + { + // If no manufacturers specified then there is nothing to map + if (passedManufacturerIds == null) + { + return; + } + var productmanufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id); + var unusedProductManufacturers = productmanufacturers.Where(x => !passedManufacturerIds.Contains(x.Id)).ToList(); + + // remove all manufacturers bindins that are not passed + foreach (var unusedProductManufacturer in unusedProductManufacturers) + { + _manufacturerService.DeleteProductManufacturer(unusedProductManufacturer); + } + + foreach (var passedManufacturerId in passedManufacturerIds) + { + // not part of existing manufacturers so we will create a new one + if (productmanufacturers.All(x => x.Id != passedManufacturerId)) + { + // if manufacturer does not exist we simply ignore it, otherwise add it to the product + var manufacturer = _manufacturerService.GetManufacturerById(passedManufacturerId); + if (manufacturer != null) + { + _manufacturerService.InsertProductManufacturer(new ProductManufacturer + { + ProductId = product.Id, + ManufacturerId = manufacturer.Id + }); + } + } + } + } + private void UpdateAssociatedProducts(Product product, List passedAssociatedProductIds) + { + // If no associated products specified then there is nothing to map + if (passedAssociatedProductIds == null) + return; + + var noLongerAssociatedProducts = + _productService.GetAssociatedProducts(product.Id, showHidden: true) + .Where(p => !passedAssociatedProductIds.Contains(p.Id)); + + // update all products that are no longer associated with our product + foreach (var noLongerAssocuatedProduct in noLongerAssociatedProducts) + { + noLongerAssocuatedProduct.ParentGroupedProductId = 0; + _productService.UpdateProduct(noLongerAssocuatedProduct); + } + + var newAssociatedProducts = _productService.GetProductsByIds(passedAssociatedProductIds.ToArray()); + foreach (var newAssociatedProduct in newAssociatedProducts) + { + newAssociatedProduct.ParentGroupedProductId = product.Id; + _productService.UpdateProduct(newAssociatedProduct); + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/ShoppingCartItemsController.cs b/Controllers/ShoppingCartItemsController.cs similarity index 86% rename from Nop.Plugin.Api/Controllers/ShoppingCartItemsController.cs rename to Controllers/ShoppingCartItemsController.cs index da2d6bb..f92e66c 100644 --- a/Nop.Plugin.Api/Controllers/ShoppingCartItemsController.cs +++ b/Controllers/ShoppingCartItemsController.cs @@ -1,358 +1,355 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.Factories; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Plugin.Api.ModelBinders; -using Nop.Plugin.Api.Models.ShoppingCartsParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Orders; -using Nop.Services.Security; -using Nop.Services.Stores; -using Nop.Plugin.Api.Helpers; -using Nop.Core; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class ShoppingCartItemsController : BaseApiController - { - private readonly IShoppingCartItemApiService _shoppingCartItemApiService; - private readonly IShoppingCartService _shoppingCartService; - private readonly IProductService _productService; - private readonly IFactory _factory; - private readonly IProductAttributeConverter _productAttributeConverter; - private readonly IDTOHelper _dtoHelper; - private readonly IStoreContext _storeContext; - - public ShoppingCartItemsController(IShoppingCartItemApiService shoppingCartItemApiService, - IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IShoppingCartService shoppingCartService, - IProductService productService, - IFactory factory, - IPictureService pictureService, - IProductAttributeConverter productAttributeConverter, - IDTOHelper dtoHelper, - IStoreContext storeContext) - : base(jsonFieldsSerializer, - aclService, - customerService, - storeMappingService, - storeService, - discountService, - customerActivityService, - localizationService, - pictureService) - { - _shoppingCartItemApiService = shoppingCartItemApiService; - _shoppingCartService = shoppingCartService; - _productService = productService; - _factory = factory; - _productAttributeConverter = productAttributeConverter; - _dtoHelper = dtoHelper; - _storeContext = storeContext; - } - - /// - /// Receive a list of all shopping cart items - /// - /// OK - /// Bad Request - /// Unauthorized - [HttpGet] - [Route("/api/shopping_cart_items")] - [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetShoppingCartItems(ShoppingCartItemsParametersModel parameters) - { - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); - } - - IList shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(customerId: null, - createdAtMin: parameters.CreatedAtMin, - createdAtMax: parameters.CreatedAtMax, - updatedAtMin: parameters.UpdatedAtMin, - updatedAtMax: parameters.UpdatedAtMax, - limit: parameters.Limit, - page: parameters.Page); - - var shoppingCartItemsDtos = shoppingCartItems.Select(shoppingCartItem => - { - return _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItem); - }).ToList(); - - var shoppingCartsRootObject = new ShoppingCartItemsRootObject() - { - ShoppingCartItems = shoppingCartItemsDtos - }; - - var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - /// - /// Receive a list of all shopping cart items by customer id - /// - /// Id of the customer whoes shopping cart items you want to get - /// - /// OK - /// Bad Request - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/shopping_cart_items/{customerId}")] - [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetShoppingCartItemsByCustomerId(int customerId, ShoppingCartItemsForCustomerParametersModel parameters) - { - if (customerId <= Configurations.DefaultCustomerId) - { - return Error(HttpStatusCode.BadRequest, "customer_id", "invalid customer_id"); - } - - if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) - { - return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); - } - - if (parameters.Page < Configurations.DefaultPageValue) - { - return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); - } - - IList shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(customerId, - parameters.CreatedAtMin, - parameters.CreatedAtMax, parameters.UpdatedAtMin, - parameters.UpdatedAtMax, parameters.Limit, - parameters.Page); - - if (shoppingCartItems == null) - { - return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); - } - - var shoppingCartItemsDtos = shoppingCartItems - .Select(shoppingCartItem => _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItem)) - .ToList(); - - var shoppingCartsRootObject = new ShoppingCartItemsRootObject() - { - ShoppingCartItems = shoppingCartItemsDtos - }; - - var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, parameters.Fields); - - return new RawJsonActionResult(json); - } - - [HttpPost] - [Route("/api/shopping_cart_items")] - [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(string), 422)] - public IActionResult CreateShoppingCartItem([ModelBinder(typeof(JsonModelBinder))] Delta shoppingCartItemDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - var newShoppingCartItem = _factory.Initialize(); - shoppingCartItemDelta.Merge(newShoppingCartItem); - - // We know that the product id and customer id will be provided because they are required by the validator. - // TODO: validate - var product = _productService.GetProductById(newShoppingCartItem.ProductId); - - if (product == null) - { - return Error(HttpStatusCode.NotFound, "product", "not found"); - } - - var customer = CustomerService.GetCustomerById(newShoppingCartItem.CustomerId); - - if (customer == null) - { - return Error(HttpStatusCode.NotFound, "customer", "not found"); - } - - var shoppingCartType = (ShoppingCartType)Enum.Parse(typeof(ShoppingCartType), shoppingCartItemDelta.Dto.ShoppingCartType); - - if (!product.IsRental) - { - newShoppingCartItem.RentalStartDateUtc = null; - newShoppingCartItem.RentalEndDateUtc = null; - } - - var attributesXml =_productAttributeConverter.ConvertToXml(shoppingCartItemDelta.Dto.Attributes, product.Id); - - var currentStoreId = _storeContext.CurrentStore.Id; - - var warnings = _shoppingCartService.AddToCart(customer, product, shoppingCartType, currentStoreId, attributesXml, 0M, - newShoppingCartItem.RentalStartDateUtc, newShoppingCartItem.RentalEndDateUtc, - shoppingCartItemDelta.Dto.Quantity ?? 1); - - if (warnings.Count > 0) - { - foreach (var warning in warnings) - { - ModelState.AddModelError("shopping cart item", warning); - } - - return Error(HttpStatusCode.BadRequest); - } - else { - // the newly added shopping cart item should be the last one - newShoppingCartItem = customer.ShoppingCartItems.LastOrDefault(); - } - - // Preparing the result dto of the new product category mapping - var newShoppingCartItemDto = _dtoHelper.PrepareShoppingCartItemDTO(newShoppingCartItem); - - var shoppingCartsRootObject = new ShoppingCartItemsRootObject(); - - shoppingCartsRootObject.ShoppingCartItems.Add(newShoppingCartItemDto); - - var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpPut] - [Route("/api/shopping_cart_items/{id}")] - [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), 422)] - public IActionResult UpdateShoppingCartItem([ModelBinder(typeof(JsonModelBinder))] Delta shoppingCartItemDelta) - { - // Here we display the errors if the validation has failed at some point. - if (!ModelState.IsValid) - { - return Error(); - } - - // We kno that the id will be valid integer because the validation for this happens in the validator which is executed by the model binder. - var shoppingCartItemForUpdate = _shoppingCartItemApiService.GetShoppingCartItem(shoppingCartItemDelta.Dto.Id); - - if (shoppingCartItemForUpdate == null) - { - return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); - } - - shoppingCartItemDelta.Merge(shoppingCartItemForUpdate); - - if (!shoppingCartItemForUpdate.Product.IsRental) - { - shoppingCartItemForUpdate.RentalStartDateUtc = null; - shoppingCartItemForUpdate.RentalEndDateUtc = null; - } - - if (shoppingCartItemDelta.Dto.Attributes != null) - { - shoppingCartItemForUpdate.AttributesXml = _productAttributeConverter.ConvertToXml(shoppingCartItemDelta.Dto.Attributes, shoppingCartItemForUpdate.Product.Id); - } - - // The update time is set in the service. - var warnings = _shoppingCartService.UpdateShoppingCartItem(shoppingCartItemForUpdate.Customer, shoppingCartItemForUpdate.Id, - shoppingCartItemForUpdate.AttributesXml, shoppingCartItemForUpdate.CustomerEnteredPrice, - shoppingCartItemForUpdate.RentalStartDateUtc, shoppingCartItemForUpdate.RentalEndDateUtc, - shoppingCartItemForUpdate.Quantity); - - if (warnings.Count > 0) - { - foreach (var warning in warnings) - { - ModelState.AddModelError("shopping cart item", warning); - } - - return Error(HttpStatusCode.BadRequest); - } - else - { - shoppingCartItemForUpdate = _shoppingCartItemApiService.GetShoppingCartItem(shoppingCartItemForUpdate.Id); - } - - // Preparing the result dto of the new product category mapping - var newShoppingCartItemDto = _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItemForUpdate); - - var shoppingCartsRootObject = new ShoppingCartItemsRootObject(); - - shoppingCartsRootObject.ShoppingCartItems.Add(newShoppingCartItemDto); - - var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, string.Empty); - - return new RawJsonActionResult(json); - } - - [HttpDelete] - [Route("/api/shopping_cart_items/{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult DeleteShoppingCartItem(int id) - { - if (id <= 0) - { - return Error(HttpStatusCode.BadRequest, "id", "invalid id"); - } - - var shoppingCartItemForDelete = _shoppingCartItemApiService.GetShoppingCartItem(id); - - if (shoppingCartItemForDelete == null) - { - return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); - } - - _shoppingCartService.DeleteShoppingCartItem(shoppingCartItemForDelete); - - //activity log - CustomerActivityService.InsertActivity("DeleteShoppingCartItem", LocalizationService.GetResource("ActivityLog.DeleteShoppingCartItem"), shoppingCartItemForDelete); - - return new RawJsonActionResult("{}"); - } - } +using Microsoft.AspNetCore.Mvc; +using Nop.Core; +using Nop.Core.Domain.Orders; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Models.ShoppingCartsParameters; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Orders; +using Nop.Services.Security; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Controllers +{ + public class ShoppingCartItemsController : BaseApiController + { + private readonly IShoppingCartItemApiService _shoppingCartItemApiService; + private readonly IShoppingCartService _shoppingCartService; + private readonly IProductService _productService; + private readonly IFactory _factory; + private readonly IProductAttributeConverter _productAttributeConverter; + private readonly IDTOHelper _dtoHelper; + private readonly IStoreContext _storeContext; + + public ShoppingCartItemsController(IShoppingCartItemApiService shoppingCartItemApiService, + IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IShoppingCartService shoppingCartService, + IProductService productService, + IFactory factory, + IPictureService pictureService, + IProductAttributeConverter productAttributeConverter, + IDTOHelper dtoHelper, + IStoreContext storeContext) + : base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _shoppingCartItemApiService = shoppingCartItemApiService; + _shoppingCartService = shoppingCartService; + _productService = productService; + _factory = factory; + _productAttributeConverter = productAttributeConverter; + _dtoHelper = dtoHelper; + _storeContext = storeContext; + } + + /// + /// Receive a list of all shopping cart items + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/shopping_cart_items")] + [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetShoppingCartItems(ShoppingCartItemsParametersModel parameters) + { + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); + } + + IList shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(customerId: null, + createdAtMin: parameters.CreatedAtMin, + createdAtMax: parameters.CreatedAtMax, + updatedAtMin: parameters.UpdatedAtMin, + updatedAtMax: parameters.UpdatedAtMax, + limit: parameters.Limit, + page: parameters.Page); + + var shoppingCartItemsDtos = shoppingCartItems.Select(shoppingCartItem => + { + return _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItem); + }).ToList(); + + var shoppingCartsRootObject = new ShoppingCartItemsRootObject() + { + ShoppingCartItems = shoppingCartItemsDtos + }; + + var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + /// + /// Receive a list of all shopping cart items by customer id + /// + /// Id of the customer whoes shopping cart items you want to get + /// + /// OK + /// Bad Request + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/shopping_cart_items/{customerId}")] + [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetShoppingCartItemsByCustomerId(int customerId, ShoppingCartItemsForCustomerParametersModel parameters) + { + if (customerId <= Configurations.DefaultCustomerId) + { + return Error(HttpStatusCode.BadRequest, "customer_id", "invalid customer_id"); + } + + if (parameters.Limit < Configurations.MinLimit || parameters.Limit > Configurations.MaxLimit) + { + return Error(HttpStatusCode.BadRequest, "limit", "invalid limit parameter"); + } + + if (parameters.Page < Configurations.DefaultPageValue) + { + return Error(HttpStatusCode.BadRequest, "page", "invalid page parameter"); + } + + IList shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(customerId, + parameters.CreatedAtMin, + parameters.CreatedAtMax, parameters.UpdatedAtMin, + parameters.UpdatedAtMax, parameters.Limit, + parameters.Page); + + if (shoppingCartItems == null) + { + return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); + } + + var shoppingCartItemsDtos = shoppingCartItems + .Select(shoppingCartItem => _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItem)) + .ToList(); + + var shoppingCartsRootObject = new ShoppingCartItemsRootObject() + { + ShoppingCartItems = shoppingCartItemsDtos + }; + + var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, parameters.Fields); + + return new RawJsonActionResult(json); + } + + [HttpPost] + [Route("/api/shopping_cart_items")] + [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(string), 422)] + public IActionResult CreateShoppingCartItem( + [ModelBinder(typeof(JsonModelBinder))] + Delta shoppingCartItemDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + var newShoppingCartItem = _factory.Initialize(); + shoppingCartItemDelta.Merge(newShoppingCartItem); + + // We know that the product id and customer id will be provided because they are required by the validator. + // TODO: validate + var product = _productService.GetProductById(newShoppingCartItem.ProductId); + + if (product == null) + { + return Error(HttpStatusCode.NotFound, "product", "not found"); + } + + var customer = CustomerService.GetCustomerById(newShoppingCartItem.CustomerId); + + if (customer == null) + { + return Error(HttpStatusCode.NotFound, "customer", "not found"); + } + + var shoppingCartType = (ShoppingCartType)Enum.Parse(typeof(ShoppingCartType), shoppingCartItemDelta.Dto.ShoppingCartType); + + if (!product.IsRental) + { + newShoppingCartItem.RentalStartDateUtc = null; + newShoppingCartItem.RentalEndDateUtc = null; + } + + var attributesXml = _productAttributeConverter.ConvertToXml(shoppingCartItemDelta.Dto.Attributes, product.Id); + + var currentStoreId = _storeContext.CurrentStore.Id; + + var warnings = _shoppingCartService.AddToCart(customer, product, shoppingCartType, currentStoreId, attributesXml, 0M, + newShoppingCartItem.RentalStartDateUtc, newShoppingCartItem.RentalEndDateUtc, + shoppingCartItemDelta.Dto.Quantity ?? 1); + + if (warnings.Count > 0) + { + foreach (var warning in warnings) + { + ModelState.AddModelError("shopping cart item", warning); + } + + return Error(HttpStatusCode.BadRequest); + } + // the newly added shopping cart item should be the last one + newShoppingCartItem = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart).LastOrDefault(); + + // Preparing the result dto of the new product category mapping + var newShoppingCartItemDto = _dtoHelper.PrepareShoppingCartItemDTO(newShoppingCartItem); + + var shoppingCartsRootObject = new ShoppingCartItemsRootObject(); + + shoppingCartsRootObject.ShoppingCartItems.Add(newShoppingCartItemDto); + + var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + [HttpPut] + [Route("/api/shopping_cart_items/{id}")] + [ProducesResponseType(typeof(ShoppingCartItemsRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), 422)] + public IActionResult UpdateShoppingCartItem( + [ModelBinder(typeof(JsonModelBinder))] + Delta shoppingCartItemDelta) + { + // Here we display the errors if the validation has failed at some point. + if (!ModelState.IsValid) + { + return Error(); + } + + // We kno that the id will be valid integer because the validation for this happens in the validator which is executed by the model binder. + var shoppingCartItemForUpdate = _shoppingCartItemApiService.GetShoppingCartItem(shoppingCartItemDelta.Dto.Id); + + if (shoppingCartItemForUpdate == null) + { + return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); + } + + shoppingCartItemDelta.Merge(shoppingCartItemForUpdate); + + if (!_productService.GetProductById(shoppingCartItemForUpdate.ProductId).IsRental) + { + shoppingCartItemForUpdate.RentalStartDateUtc = null; + shoppingCartItemForUpdate.RentalEndDateUtc = null; + } + + if (shoppingCartItemDelta.Dto.Attributes != null) + { + shoppingCartItemForUpdate.AttributesXml = + _productAttributeConverter.ConvertToXml(shoppingCartItemDelta.Dto.Attributes, shoppingCartItemForUpdate.ProductId); + } + + var customer = CustomerService.GetCustomerById(shoppingCartItemForUpdate.CustomerId); + // The update time is set in the service. + var warnings = _shoppingCartService.UpdateShoppingCartItem(customer, shoppingCartItemForUpdate.Id, + shoppingCartItemForUpdate.AttributesXml, shoppingCartItemForUpdate.CustomerEnteredPrice, + shoppingCartItemForUpdate.RentalStartDateUtc, shoppingCartItemForUpdate.RentalEndDateUtc, + shoppingCartItemForUpdate.Quantity); + + if (warnings.Count > 0) + { + foreach (var warning in warnings) + { + ModelState.AddModelError("shopping cart item", warning); + } + + return Error(HttpStatusCode.BadRequest); + } + shoppingCartItemForUpdate = _shoppingCartItemApiService.GetShoppingCartItem(shoppingCartItemForUpdate.Id); + + // Preparing the result dto of the new product category mapping + var newShoppingCartItemDto = _dtoHelper.PrepareShoppingCartItemDTO(shoppingCartItemForUpdate); + + var shoppingCartsRootObject = new ShoppingCartItemsRootObject(); + + shoppingCartsRootObject.ShoppingCartItems.Add(newShoppingCartItemDto); + + var json = JsonFieldsSerializer.Serialize(shoppingCartsRootObject, string.Empty); + + return new RawJsonActionResult(json); + } + + [HttpDelete] + [Route("/api/shopping_cart_items/{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult DeleteShoppingCartItem(int id) + { + if (id <= 0) + { + return Error(HttpStatusCode.BadRequest, "id", "invalid id"); + } + + var shoppingCartItemForDelete = _shoppingCartItemApiService.GetShoppingCartItem(id); + + if (shoppingCartItemForDelete == null) + { + return Error(HttpStatusCode.NotFound, "shopping_cart_item", "not found"); + } + + _shoppingCartService.DeleteShoppingCartItem(shoppingCartItemForDelete); + + //activity log + CustomerActivityService.InsertActivity("DeleteShoppingCartItem", LocalizationService.GetResource("ActivityLog.DeleteShoppingCartItem"), shoppingCartItemForDelete); + + return new RawJsonActionResult("{}"); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/SpecificationAttributesController.cs b/Controllers/SpecificationAttributesController.cs similarity index 97% rename from Nop.Plugin.Api/Controllers/SpecificationAttributesController.cs rename to Controllers/SpecificationAttributesController.cs index a6a3732..9d6c82b 100644 --- a/Nop.Plugin.Api/Controllers/SpecificationAttributesController.cs +++ b/Controllers/SpecificationAttributesController.cs @@ -1,11 +1,9 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.DTOs.Errors; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.SpecificationAttributes; using Nop.Plugin.Api.Helpers; using Nop.Plugin.Api.JSON.ActionResults; using Nop.Plugin.Api.JSON.Serializers; @@ -22,10 +20,10 @@ using Nop.Services.Stores; using System.Linq; using System.Net; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Controllers { - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class SpecificationAttributesController : BaseApiController { private readonly ISpecificationAttributeService _specificationAttributeService; diff --git a/Nop.Plugin.Api/Controllers/StoreController.cs b/Controllers/StoreController.cs similarity index 89% rename from Nop.Plugin.Api/Controllers/StoreController.cs rename to Controllers/StoreController.cs index 352de62..36073d8 100644 --- a/Nop.Plugin.Api/Controllers/StoreController.cs +++ b/Controllers/StoreController.cs @@ -1,123 +1,122 @@ -using Nop.Core; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.Stores; -using Nop.Plugin.Api.JSON.ActionResults; -using Nop.Services.Customers; -using Nop.Services.Discounts; -using Nop.Services.Localization; -using Nop.Services.Logging; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Stores; -using System.Collections.Generic; -using System.Net; -using Nop.Plugin.Api.Helpers; - -namespace Nop.Plugin.Api.Controllers -{ - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Mvc; - using DTOs.Errors; - using JSON.Serializers; - - [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - public class StoreController : BaseApiController - { - private readonly IStoreContext _storeContext; - private readonly IDTOHelper _dtoHelper; - - public StoreController(IJsonFieldsSerializer jsonFieldsSerializer, - IAclService aclService, - ICustomerService customerService, - IStoreMappingService storeMappingService, - IStoreService storeService, - IDiscountService discountService, - ICustomerActivityService customerActivityService, - ILocalizationService localizationService, - IPictureService pictureService, - IStoreContext storeContext, - IDTOHelper dtoHelper) - : base(jsonFieldsSerializer, - aclService, - customerService, - storeMappingService, - storeService, - discountService, - customerActivityService, - localizationService, - pictureService) - { - _storeContext = storeContext; - _dtoHelper = dtoHelper; - } - - /// - /// Retrieve category by spcified id - /// - /// Fields from the category you want your json to contain - /// OK - /// Not Found - /// Unauthorized - [HttpGet] - [Route("/api/current_store")] - [ProducesResponseType(typeof(StoresRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetCurrentStore(string fields = "") - { - var store = _storeContext.CurrentStore; - - if (store == null) - { - return Error(HttpStatusCode.NotFound, "store", "store not found"); - } - - var storeDto = _dtoHelper.PrepareStoreDTO(store); - - var storesRootObject = new StoresRootObject(); - - storesRootObject.Stores.Add(storeDto); - - var json = JsonFieldsSerializer.Serialize(storesRootObject, fields); - - return new RawJsonActionResult(json); - } - - /// - /// Retrieve all stores - /// - /// Fields from the store you want your json to contain - /// OK - /// Unauthorized - [HttpGet] - [Route("/api/stores")] - [ProducesResponseType(typeof(StoresRootObject), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] - [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] - [GetRequestsErrorInterceptorActionFilter] - public IActionResult GetAllStores(string fields = "") - { - var allStores = StoreService.GetAllStores(); - - IList storesAsDto = new List(); - - foreach (var store in allStores) - { - var storeDto = _dtoHelper.PrepareStoreDTO(store); - - storesAsDto.Add(storeDto); - } - - var storesRootObject = new StoresRootObject() - { - Stores = storesAsDto - }; - - var json = JsonFieldsSerializer.Serialize(storesRootObject, fields); - - return new RawJsonActionResult(json); - } - } -} +using System.Collections.Generic; +using System.Net; +using Microsoft.AspNetCore.Mvc; +using Nop.Core; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.Stores; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; + +namespace Nop.Plugin.Api.Controllers +{ + + //[ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + public class StoreController : BaseApiController + { + private readonly IStoreContext _storeContext; + private readonly IDTOHelper _dtoHelper; + + public StoreController(IJsonFieldsSerializer jsonFieldsSerializer, + IAclService aclService, + ICustomerService customerService, + IStoreMappingService storeMappingService, + IStoreService storeService, + IDiscountService discountService, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IPictureService pictureService, + IStoreContext storeContext, + IDTOHelper dtoHelper) + : base(jsonFieldsSerializer, + aclService, + customerService, + storeMappingService, + storeService, + discountService, + customerActivityService, + localizationService, + pictureService) + { + _storeContext = storeContext; + _dtoHelper = dtoHelper; + } + + /// + /// Retrieve category by spcified id + /// + /// Fields from the category you want your json to contain + /// OK + /// Not Found + /// Unauthorized + [HttpGet] + [Route("/api/current_store")] + [ProducesResponseType(typeof(StoresRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetCurrentStore(string fields = "") + { + var store = _storeContext.CurrentStore; + + if (store == null) + { + return Error(HttpStatusCode.NotFound, "store", "store not found"); + } + + var storeDto = _dtoHelper.PrepareStoreDTO(store); + + var storesRootObject = new StoresRootObject(); + + storesRootObject.Stores.Add(storeDto); + + var json = JsonFieldsSerializer.Serialize(storesRootObject, fields); + + return new RawJsonActionResult(json); + } + + /// + /// Retrieve all stores + /// + /// Fields from the store you want your json to contain + /// OK + /// Unauthorized + [HttpGet] + [Route("/api/stores")] + [ProducesResponseType(typeof(StoresRootObject), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetAllStores(string fields = "") + { + var allStores = StoreService.GetAllStores(); + + IList storesAsDto = new List(); + + foreach (var store in allStores) + { + var storeDto = _dtoHelper.PrepareStoreDTO(store); + + storesAsDto.Add(storeDto); + } + + var storesRootObject = new StoresRootObject() + { + Stores = storesAsDto + }; + + var json = JsonFieldsSerializer.Serialize(storesRootObject, fields); + + return new RawJsonActionResult(json); + } + } +} diff --git a/Controllers/TaxCategoryController.cs b/Controllers/TaxCategoryController.cs new file mode 100644 index 0000000..b6cc18d --- /dev/null +++ b/Controllers/TaxCategoryController.cs @@ -0,0 +1,89 @@ +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Errors; +using Nop.Plugin.Api.DTO.TaxCategory; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.ActionResults; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.Models.ProductsParameters; +using Nop.Services.Catalog; +using Nop.Services.Customers; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Security; +using Nop.Services.Stores; +using Nop.Services.Tax; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Nop.Plugin.Api.Controllers +{ + + public class TaxCategoryController : BaseApiController + { + //private readonly IProductApiService _productApiService; + //private readonly IProductService _productService; + //private readonly IUrlRecordService _urlRecordService; + //private readonly IManufacturerService _manufacturerService; + private readonly IFactory _factory; + //private readonly IProductTagService _productTagService; + //private readonly IProductAttributeService _productAttributeService; + private readonly ITaxCategoryService _taxCategoryService; + private readonly IDTOHelper _dtoHelper; + + + public TaxCategoryController( + IJsonFieldsSerializer jsonFieldsSerializer, + ICustomerActivityService customerActivityService, + ILocalizationService localizationService, + IFactory factory, + IAclService aclService, + IStoreMappingService storeMappingService, + IStoreService storeService, + ICustomerService customerService, + IDiscountService discountService, + IPictureService pictureService, + IProductTagService productTagService, + ITaxCategoryService taxCategoryService, + IDTOHelper dtoHelper) : base(jsonFieldsSerializer, aclService, customerService, storeMappingService, storeService, discountService, customerActivityService, localizationService, pictureService) + { + _factory = factory; + _dtoHelper = dtoHelper; + _taxCategoryService = taxCategoryService; + } + + /// + /// Receive a list of all products + /// + /// OK + /// Bad Request + /// Unauthorized + [HttpGet] + [Route("/api/taxcategories")] + [ProducesResponseType(typeof(TaxCategoryRootObjectDto), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] + [ProducesResponseType(typeof(ErrorsRootObject), (int)HttpStatusCode.BadRequest)] + [GetRequestsErrorInterceptorActionFilter] + public IActionResult GetTaxCategories(TaxCategoriesParametersModel parameters) + { + var allTaxCategories = _taxCategoryService.GetAllTaxCategories(); + + IList taxCategoriesAsDtos = allTaxCategories.Select(taxCategory => _dtoHelper.PrepareTaxCategoryDTO(taxCategory)).ToList(); + + var taxCategoriesRootObject = new TaxCategoryRootObjectDto() + { + TaxCategories = taxCategoriesAsDtos + }; + + var json = JsonFieldsSerializer.Serialize(taxCategoriesRootObject, null); + + return new RawJsonActionResult(json); + } + + } +} \ No newline at end of file diff --git a/Controllers/TokenController.cs b/Controllers/TokenController.cs new file mode 100644 index 0000000..b2ebdb1 --- /dev/null +++ b/Controllers/TokenController.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.IdentityModel.Tokens; +using Nop.Core.Domain.Customers; +using Nop.Plugin.Api.Configuration; +using Nop.Plugin.Api.Domain; +using Nop.Plugin.Api.Infrastructure; +using Nop.Plugin.Api.Models.Authentication; +using Nop.Services.Customers; +using Nop.Services.Logging; + +namespace Nop.Plugin.Api.Controllers +{ + [AllowAnonymous] + public class TokenController : Controller + { + private readonly ApiConfiguration _apiConfiguration; + private readonly ApiSettings _apiSettings; + private readonly ICustomerActivityService _customerActivityService; + private readonly ICustomerRegistrationService _customerRegistrationService; + private readonly ICustomerService _customerService; + private readonly CustomerSettings _customerSettings; + + public TokenController( + ICustomerService customerService, + ICustomerRegistrationService customerRegistrationService, + ICustomerActivityService customerActivityService, + CustomerSettings customerSettings, + ApiSettings apiSettings, + ApiConfiguration apiConfiguration) + { + _customerService = customerService; + _customerRegistrationService = customerRegistrationService; + _customerActivityService = customerActivityService; + _customerSettings = customerSettings; + _apiSettings = apiSettings; + _apiConfiguration = apiConfiguration; + } + + [Route("/token")] + [HttpGet] + public IActionResult Create(TokenRequest model) + { + if (string.IsNullOrEmpty(model.Username)) + { + return Json(new TokenResponse("Missing username")); + } + + if (string.IsNullOrEmpty(model.Password)) + { + return Json(new TokenResponse("Missing password")); + } + + var customer = ValidateUser(model); + + if (customer != null) + { + return Json(GenerateToken(customer)); + } + + return Forbid();// new HttpStatusCodeResult(HttpStatusCode.Forbidden);// Json(new TokenResponse("Access Denied")); + } + + private CustomerLoginResults LoginCustomer(TokenRequest model) + { + var loginResult = _customerRegistrationService + .ValidateCustomer(model.Username, model.Password); + + return loginResult; + } + + private Customer ValidateUser(TokenRequest model) + { + var result = LoginCustomer(model); + + if (result == CustomerLoginResults.Successful) + { + var customer = _customerSettings.UsernamesEnabled + ? _customerService.GetCustomerByUsername(model.Username) + : _customerService.GetCustomerByEmail(model.Username); + + + //activity log + _customerActivityService.InsertActivity(customer, "Api.TokenRequest", "User API token request", customer); + + return customer; + } + + return null; + } + + private int GetTokenExpiryInDays() + { + return _apiSettings.TokenExpiryInDays <= 0 + ? Constants.Configurations.DefaultAccessTokenExpirationInDays + : _apiSettings.TokenExpiryInDays; + } + + private TokenResponse GenerateToken(Customer customer) + { + var expiresInSeconds = new DateTimeOffset(DateTime.Now.AddDays(GetTokenExpiryInDays())).ToUnixTimeSeconds(); + + var claims = new List + { + new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), + new Claim(JwtRegisteredClaimNames.Exp, expiresInSeconds.ToString()), + new Claim(ClaimTypes.Email, customer.Email), + new Claim(ClaimTypes.NameIdentifier, customer.CustomerGuid.ToString()), + _customerSettings.UsernamesEnabled + ? new Claim(ClaimTypes.Name, customer.Username) + : new Claim(ClaimTypes.Name, customer.Email) + }; + + var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_apiConfiguration.SecurityKey)), + SecurityAlgorithms.HmacSha256); + + var token = new JwtSecurityToken(new JwtHeader(signingCredentials), new JwtPayload(claims)); + var accessToken = new JwtSecurityTokenHandler().WriteToken(token); + + + return new TokenResponse(accessToken, expiresInSeconds); + } + } +} diff --git a/Nop.Plugin.Api/Converters/ApiTypeConverter.cs b/Converters/ApiTypeConverter.cs similarity index 96% rename from Nop.Plugin.Api/Converters/ApiTypeConverter.cs rename to Converters/ApiTypeConverter.cs index b27c343..5107096 100644 --- a/Nop.Plugin.Api/Converters/ApiTypeConverter.cs +++ b/Converters/ApiTypeConverter.cs @@ -1,125 +1,125 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; - -namespace Nop.Plugin.Api.Converters -{ - public class ApiTypeConverter : IApiTypeConverter - { - /// - /// Converts the value, which should be in ISO 8601 format to UTC time or null if not valid - /// - /// The time format in ISO 8601. If no timezone or offset specified we assume it is in UTC - /// The time in UTC or null if the time is not valid - public DateTime? ToUtcDateTimeNullable(string value) - { - DateTime result; - - var formats = new string[] - { - "yyyy", - "yyyy-MM", - "yyyy-MM-dd", - "yyyy-MM-ddTHH:mm", - "yyyy-MM-ddTHH:mm:ss", - "yyyy-MM-ddTHH:mm:sszzz", - "yyyy-MM-ddTHH:mm:ss.FFFFFFFK" - }; - - if (DateTime.TryParseExact(value, formats, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result)) - { - // only if parsed in Local time then we need to convert it to UTC - if (result.Kind == DateTimeKind.Local) - { - return result.ToUniversalTime(); - } - - return result; - } - - return null; - } - - public int ToInt(string value) - { - int result; - - if (int.TryParse(value, out result)) - { - return result; - } - - return 0; - } - - public int? ToIntNullable(string value) - { - int result; - - if (int.TryParse(value, out result)) - { - return result; - } - - return null; - } - - public IList ToListOfInts(string value) - { - if (!string.IsNullOrEmpty(value)) - { - var stringIds = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - var intIds = new List(); - - foreach (var id in stringIds) - { - int intId; - if (int.TryParse(id, out intId)) - { - intIds.Add(intId); - } - } - - intIds = intIds.Distinct().ToList(); - return intIds.Count > 0 ? intIds : null; - } - - return null; - } - - public bool? ToStatus(string value) - { - if (!string.IsNullOrEmpty(value)) - { - if (value.Equals("published", StringComparison.InvariantCultureIgnoreCase)) - { - return true; - } - else if (value.Equals("unpublished", StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - - return null; - } - - public object ToEnumNullable(string value, Type type) - { - if (!string.IsNullOrEmpty(value)) - { - var enumType = Nullable.GetUnderlyingType(type); - - var enumNames = enumType.GetEnumNames(); - - if (enumNames.Any(x => x.ToLowerInvariant().Equals(value.ToLowerInvariant()))) - { - return Enum.Parse(enumType, value, true); - } - } - - return null; - } - } +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Nop.Plugin.Api.Converters +{ + public class ApiTypeConverter : IApiTypeConverter + { + /// + /// Converts the value, which should be in ISO 8601 format to UTC time or null if not valid + /// + /// The time format in ISO 8601. If no timezone or offset specified we assume it is in UTC + /// The time in UTC or null if the time is not valid + public DateTime? ToUtcDateTimeNullable(string value) + { + DateTime result; + + var formats = new string[] + { + "yyyy", + "yyyy-MM", + "yyyy-MM-dd", + "yyyy-MM-ddTHH:mm", + "yyyy-MM-ddTHH:mm:ss", + "yyyy-MM-ddTHH:mm:sszzz", + "yyyy-MM-ddTHH:mm:ss.FFFFFFFK" + }; + + if (DateTime.TryParseExact(value, formats, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result)) + { + // only if parsed in Local time then we need to convert it to UTC + if (result.Kind == DateTimeKind.Local) + { + return result.ToUniversalTime(); + } + + return result; + } + + return null; + } + + public int ToInt(string value) + { + int result; + + if (int.TryParse(value, out result)) + { + return result; + } + + return 0; + } + + public int? ToIntNullable(string value) + { + int result; + + if (int.TryParse(value, out result)) + { + return result; + } + + return null; + } + + public IList ToListOfInts(string value) + { + if (!string.IsNullOrEmpty(value)) + { + var stringIds = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); + var intIds = new List(); + + foreach (var id in stringIds) + { + int intId; + if (int.TryParse(id, out intId)) + { + intIds.Add(intId); + } + } + + intIds = intIds.Distinct().ToList(); + return intIds.Count > 0 ? intIds : null; + } + + return null; + } + + public bool? ToStatus(string value) + { + if (!string.IsNullOrEmpty(value)) + { + if (value.Equals("published", StringComparison.InvariantCultureIgnoreCase)) + { + return true; + } + else if (value.Equals("unpublished", StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + + return null; + } + + public object ToEnumNullable(string value, Type type) + { + if (!string.IsNullOrEmpty(value)) + { + var enumType = Nullable.GetUnderlyingType(type); + + var enumNames = enumType.GetEnumNames(); + + if (enumNames.Any(x => x.ToLowerInvariant().Equals(value.ToLowerInvariant()))) + { + return Enum.Parse(enumType, value, true); + } + } + + return null; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Converters/IApiTypeConverter.cs b/Converters/IApiTypeConverter.cs similarity index 100% rename from Nop.Plugin.Api/Converters/IApiTypeConverter.cs rename to Converters/IApiTypeConverter.cs diff --git a/Nop.Plugin.Api/Converters/IObjectConverter.cs b/Converters/IObjectConverter.cs similarity index 100% rename from Nop.Plugin.Api/Converters/IObjectConverter.cs rename to Converters/IObjectConverter.cs diff --git a/Nop.Plugin.Api/Converters/ObjectConverter.cs b/Converters/ObjectConverter.cs similarity index 97% rename from Nop.Plugin.Api/Converters/ObjectConverter.cs rename to Converters/ObjectConverter.cs index 0d3c2a3..613ae82 100644 --- a/Nop.Plugin.Api/Converters/ObjectConverter.cs +++ b/Converters/ObjectConverter.cs @@ -1,78 +1,78 @@ -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Nop.Plugin.Api.Converters -{ - public class ObjectConverter : IObjectConverter - { - private readonly IApiTypeConverter _apiTypeConverter; - - public ObjectConverter(IApiTypeConverter apiTypeConverter) - { - _apiTypeConverter = apiTypeConverter; - } - - public T ToObject(ICollection> source) - where T : class, new() - { - var someObject = new T(); - var someObjectType = someObject.GetType(); - - if (source != null) - { - foreach (var item in source) - { - var itemKey = item.Key.Replace("_", string.Empty); - var currentProperty = someObjectType.GetProperty(itemKey, - BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); - - if (currentProperty != null) - { - currentProperty.SetValue(someObject, To(item.Value, currentProperty.PropertyType), null); - } - } - } - - return someObject; - } - - private object To(string value, Type type) - { - if (type == typeof(DateTime?)) - { - return _apiTypeConverter.ToUtcDateTimeNullable(value); - } - else if (type == typeof (int?)) - { - return _apiTypeConverter.ToIntNullable(value); - } - else if (type == typeof(int)) - { - return _apiTypeConverter.ToInt(value); - } - else if (type == typeof(List)) - { - return _apiTypeConverter.ToListOfInts(value); - } - else if(type == typeof(bool?)) - { - // Because currently status is the only boolean and we need to accept published and unpublished statuses. - return _apiTypeConverter.ToStatus(value); - } - else if (IsNullableEnum(type)) - { - return _apiTypeConverter.ToEnumNullable(value, type); - } - - // It should be the last resort, because it is not exception safe. - return Convert.ChangeType(value, type); - } - - private bool IsNullableEnum(Type t) - { - var u = Nullable.GetUnderlyingType(t); - return (u != null) && u.IsEnum; - } - } +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Nop.Plugin.Api.Converters +{ + public class ObjectConverter : IObjectConverter + { + private readonly IApiTypeConverter _apiTypeConverter; + + public ObjectConverter(IApiTypeConverter apiTypeConverter) + { + _apiTypeConverter = apiTypeConverter; + } + + public T ToObject(ICollection> source) + where T : class, new() + { + var someObject = new T(); + var someObjectType = someObject.GetType(); + + if (source != null) + { + foreach (var item in source) + { + var itemKey = item.Key.Replace("_", string.Empty); + var currentProperty = someObjectType.GetProperty(itemKey, + BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); + + if (currentProperty != null) + { + currentProperty.SetValue(someObject, To(item.Value, currentProperty.PropertyType), null); + } + } + } + + return someObject; + } + + private object To(string value, Type type) + { + if (type == typeof(DateTime?)) + { + return _apiTypeConverter.ToUtcDateTimeNullable(value); + } + else if (type == typeof (int?)) + { + return _apiTypeConverter.ToIntNullable(value); + } + else if (type == typeof(int)) + { + return _apiTypeConverter.ToInt(value); + } + else if (type == typeof(List)) + { + return _apiTypeConverter.ToListOfInts(value); + } + else if(type == typeof(bool?)) + { + // Because currently status is the only boolean and we need to accept published and unpublished statuses. + return _apiTypeConverter.ToStatus(value); + } + else if (IsNullableEnum(type)) + { + return _apiTypeConverter.ToEnumNullable(value, type); + } + + // It should be the last resort, because it is not exception safe. + return Convert.ChangeType(value, type); + } + + private bool IsNullableEnum(Type t) + { + var u = Nullable.GetUnderlyingType(t); + return (u != null) && u.IsEnum; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/DTOs/AddressDto.cs b/DTOs/AddressDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/AddressDto.cs rename to DTOs/AddressDto.cs index 74bad77..46aa05e 100644 --- a/Nop.Plugin.Api/DTOs/AddressDto.cs +++ b/DTOs/AddressDto.cs @@ -1,13 +1,11 @@ -using System; -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.Validators; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; +using System; -namespace Nop.Plugin.Api.DTOs +namespace Nop.Plugin.Api.DTO { [JsonObject(Title = "address")] - [Validator(typeof(AddressDtoValidator))] + //[Validator(typeof(AddressDtoValidator))] public class AddressDto : BaseDto { /// diff --git a/Nop.Plugin.Api/DTOs/Base/BaseDto.cs b/DTOs/Base/BaseDto.cs similarity index 80% rename from Nop.Plugin.Api/DTOs/Base/BaseDto.cs rename to DTOs/Base/BaseDto.cs index 539a687..262cfdd 100644 --- a/Nop.Plugin.Api/DTOs/Base/BaseDto.cs +++ b/DTOs/Base/BaseDto.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Base +namespace Nop.Plugin.Api.DTO.Base { public abstract class BaseDto { diff --git a/Nop.Plugin.Api/DTOs/Categories/CategoriesCountRootObject.cs b/DTOs/Categories/CategoriesCountRootObject.cs similarity index 79% rename from Nop.Plugin.Api/DTOs/Categories/CategoriesCountRootObject.cs rename to DTOs/Categories/CategoriesCountRootObject.cs index 49e6902..6f86d92 100644 --- a/Nop.Plugin.Api/DTOs/Categories/CategoriesCountRootObject.cs +++ b/DTOs/Categories/CategoriesCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Categories +namespace Nop.Plugin.Api.DTO.Categories { public class CategoriesCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/Categories/CategoriesRootObject.cs b/DTOs/Categories/CategoriesRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Categories/CategoriesRootObject.cs rename to DTOs/Categories/CategoriesRootObject.cs index 11d8252..4f1ca4c 100644 --- a/Nop.Plugin.Api/DTOs/Categories/CategoriesRootObject.cs +++ b/DTOs/Categories/CategoriesRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Categories +namespace Nop.Plugin.Api.DTO.Categories { public class CategoriesRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Categories/CategoryDto.cs b/DTOs/Categories/CategoryDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Categories/CategoryDto.cs rename to DTOs/Categories/CategoryDto.cs index 621a935..05a55c8 100644 --- a/Nop.Plugin.Api/DTOs/Categories/CategoryDto.cs +++ b/DTOs/Categories/CategoryDto.cs @@ -1,15 +1,14 @@ -using System; -using System.Collections.Generic; -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Languages; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Languages; using Nop.Plugin.Api.Validators; +using System; +using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.Categories +namespace Nop.Plugin.Api.DTO.Categories { - [Validator(typeof(CategoryDtoValidator))] + //[Validator(typeof(CategoryDtoValidator))] [JsonObject(Title = "category")] public class CategoryDto : BaseDto { @@ -138,6 +137,9 @@ public List LocalizedNames [JsonProperty("created_on_utc")] public DateTime? CreatedOnUtc { get; set; } + [JsonProperty("allow_customers_to_select_page_size")] + public bool AllowCustomersToSelectPageSize { get; set; } + /// /// Gets or sets the date and time of instance update /// diff --git a/Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRoleDto.cs b/DTOs/CustomerRoles/CustomerRoleDto.cs similarity index 96% rename from Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRoleDto.cs rename to DTOs/CustomerRoles/CustomerRoleDto.cs index 56c88c6..b05a285 100644 --- a/Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRoleDto.cs +++ b/DTOs/CustomerRoles/CustomerRoleDto.cs @@ -1,7 +1,7 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.CustomerRoles +namespace Nop.Plugin.Api.DTO.CustomerRoles { [JsonObject(Title = "customer_role")] public class CustomerRoleDto : BaseDto diff --git a/Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRolesRootObject.cs b/DTOs/CustomerRoles/CustomerRolesRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRolesRootObject.cs rename to DTOs/CustomerRoles/CustomerRolesRootObject.cs index a65a011..8450046 100644 --- a/Nop.Plugin.Api/DTOs/CustomerRoles/CustomerRolesRootObject.cs +++ b/DTOs/CustomerRoles/CustomerRolesRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.CustomerRoles +namespace Nop.Plugin.Api.DTO.CustomerRoles { public class CustomerRolesRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Customers/BaseCustomerDto.cs b/DTOs/Customers/BaseCustomerDto.cs similarity index 98% rename from Nop.Plugin.Api/DTOs/Customers/BaseCustomerDto.cs rename to DTOs/Customers/BaseCustomerDto.cs index 13670dc..83db97a 100644 --- a/Nop.Plugin.Api/DTOs/Customers/BaseCustomerDto.cs +++ b/DTOs/Customers/BaseCustomerDto.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { public class BaseCustomerDto : BaseDto { diff --git a/Nop.Plugin.Api/DTOs/Customers/CustomerAttributeMappingDto.cs b/DTOs/Customers/CustomerAttributeMappingDto.cs similarity index 85% rename from Nop.Plugin.Api/DTOs/Customers/CustomerAttributeMappingDto.cs rename to DTOs/Customers/CustomerAttributeMappingDto.cs index 6350578..8b37115 100644 --- a/Nop.Plugin.Api/DTOs/Customers/CustomerAttributeMappingDto.cs +++ b/DTOs/Customers/CustomerAttributeMappingDto.cs @@ -1,7 +1,7 @@ using Nop.Core.Domain.Common; using Nop.Core.Domain.Customers; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { public class CustomerAttributeMappingDto { diff --git a/Nop.Plugin.Api/DTOs/Customers/CustomerDto.cs b/DTOs/Customers/CustomerDto.cs similarity index 87% rename from Nop.Plugin.Api/DTOs/Customers/CustomerDto.cs rename to DTOs/Customers/CustomerDto.cs index 61db1ac..19e2906 100644 --- a/Nop.Plugin.Api/DTOs/Customers/CustomerDto.cs +++ b/DTOs/Customers/CustomerDto.cs @@ -1,14 +1,12 @@ -using System.Collections.Generic; -using FluentValidation.Attributes; -using Newtonsoft.Json; +using Newtonsoft.Json; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.Validators; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { [JsonObject(Title = "customer")] - [Validator(typeof(CustomerDtoValidator))] + //[Validator(typeof(CustomerDtoValidator))] public class CustomerDto : BaseCustomerDto { private ICollection _shoppingCartItems; diff --git a/Nop.Plugin.Api/DTOs/Customers/CustomerForShoppingCartItemDto.cs b/DTOs/Customers/CustomerForShoppingCartItemDto.cs similarity index 96% rename from Nop.Plugin.Api/DTOs/Customers/CustomerForShoppingCartItemDto.cs rename to DTOs/Customers/CustomerForShoppingCartItemDto.cs index 31ddaf9..282be19 100644 --- a/Nop.Plugin.Api/DTOs/Customers/CustomerForShoppingCartItemDto.cs +++ b/DTOs/Customers/CustomerForShoppingCartItemDto.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { // We need this DTO object to avoid loop in the entity to dto mappings. The difference is the missing ShoppingCartItems collection. [JsonObject(Title = "customers")] diff --git a/Nop.Plugin.Api/DTOs/Customers/CustomersCountRootObject.cs b/DTOs/Customers/CustomersCountRootObject.cs similarity index 79% rename from Nop.Plugin.Api/DTOs/Customers/CustomersCountRootObject.cs rename to DTOs/Customers/CustomersCountRootObject.cs index 9f84d7a..81e532e 100644 --- a/Nop.Plugin.Api/DTOs/Customers/CustomersCountRootObject.cs +++ b/DTOs/Customers/CustomersCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { public class CustomersCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/Customers/CustomersRootObject.cs b/DTOs/Customers/CustomersRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Customers/CustomersRootObject.cs rename to DTOs/Customers/CustomersRootObject.cs index aef1a99..35e6e0d 100644 --- a/Nop.Plugin.Api/DTOs/Customers/CustomersRootObject.cs +++ b/DTOs/Customers/CustomersRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { public class CustomersRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Customers/OrderCustomerDto.cs b/DTOs/Customers/OrderCustomerDto.cs similarity index 64% rename from Nop.Plugin.Api/DTOs/Customers/OrderCustomerDto.cs rename to DTOs/Customers/OrderCustomerDto.cs index 4f11f87..5970dc3 100644 --- a/Nop.Plugin.Api/DTOs/Customers/OrderCustomerDto.cs +++ b/DTOs/Customers/OrderCustomerDto.cs @@ -1,4 +1,4 @@ -namespace Nop.Plugin.Api.DTOs.Customers +namespace Nop.Plugin.Api.DTO.Customers { public class OrderCustomerDto : BaseCustomerDto { diff --git a/Nop.Plugin.Api/DTOs/Errors/ErrorsRootObject.cs b/DTOs/Errors/ErrorsRootObject.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/Errors/ErrorsRootObject.cs rename to DTOs/Errors/ErrorsRootObject.cs index 8b5f66d..48b1f02 100644 --- a/Nop.Plugin.Api/DTOs/Errors/ErrorsRootObject.cs +++ b/DTOs/Errors/ErrorsRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Errors +namespace Nop.Plugin.Api.DTO.Errors { public class ErrorsRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/ISerializableObject.cs b/DTOs/ISerializableObject.cs similarity index 83% rename from Nop.Plugin.Api/DTOs/ISerializableObject.cs rename to DTOs/ISerializableObject.cs index b323e9c..1ec4b0a 100644 --- a/Nop.Plugin.Api/DTOs/ISerializableObject.cs +++ b/DTOs/ISerializableObject.cs @@ -1,6 +1,6 @@ using System; -namespace Nop.Plugin.Api.DTOs +namespace Nop.Plugin.Api.DTO { public interface ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Images/ImageDto.cs b/DTOs/Images/ImageDto.cs similarity index 66% rename from Nop.Plugin.Api/DTOs/Images/ImageDto.cs rename to DTOs/Images/ImageDto.cs index e745115..aaf6bef 100644 --- a/Nop.Plugin.Api/DTOs/Images/ImageDto.cs +++ b/DTOs/Images/ImageDto.cs @@ -1,10 +1,11 @@ using Newtonsoft.Json; using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Images +namespace Nop.Plugin.Api.DTO.Images { [ImageValidation] - public class ImageDto + public class ImageDto : BaseDto { [JsonProperty("src")] public string Src { get; set; } @@ -17,5 +18,8 @@ public class ImageDto [JsonIgnore] public string MimeType { get; set; } + + [JsonProperty("seoFilename")] + public string SeoFilename { get; set; } } } \ No newline at end of file diff --git a/Nop.Plugin.Api/DTOs/Images/ImageMappingDto.cs b/DTOs/Images/ImageMappingDto.cs similarity index 66% rename from Nop.Plugin.Api/DTOs/Images/ImageMappingDto.cs rename to DTOs/Images/ImageMappingDto.cs index 8b3b305..777c70c 100644 --- a/Nop.Plugin.Api/DTOs/Images/ImageMappingDto.cs +++ b/DTOs/Images/ImageMappingDto.cs @@ -1,13 +1,14 @@ using Newtonsoft.Json; using Nop.Plugin.Api.Attributes; -namespace Nop.Plugin.Api.DTOs.Images +namespace Nop.Plugin.Api.DTO.Images { [ImageValidation] + [JsonObject(Title = "image")] public class ImageMappingDto : ImageDto { - [JsonProperty("id")] - public int Id { get; set; } + [JsonProperty("product_id")] + public int ProductId { get; set; } [JsonProperty("picture_id")] public int PictureId { get; set; } diff --git a/Nop.Plugin.Api/DTOs/Languages/LanguageDto.cs b/DTOs/Languages/LanguageDto.cs similarity index 97% rename from Nop.Plugin.Api/DTOs/Languages/LanguageDto.cs rename to DTOs/Languages/LanguageDto.cs index bab7703..4197bf2 100644 --- a/Nop.Plugin.Api/DTOs/Languages/LanguageDto.cs +++ b/DTOs/Languages/LanguageDto.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Languages +namespace Nop.Plugin.Api.DTO.Languages { [JsonObject(Title = "language")] public class LanguageDto : BaseDto diff --git a/Nop.Plugin.Api/DTOs/Languages/LanguagesRootObject.cs b/DTOs/Languages/LanguagesRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Languages/LanguagesRootObject.cs rename to DTOs/Languages/LanguagesRootObject.cs index 3d3f6be..e994b65 100644 --- a/Nop.Plugin.Api/DTOs/Languages/LanguagesRootObject.cs +++ b/DTOs/Languages/LanguagesRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Languages +namespace Nop.Plugin.Api.DTO.Languages { public class LanguagesRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Languages/LocalizedNameDto.cs b/DTOs/Languages/LocalizedNameDto.cs similarity index 91% rename from Nop.Plugin.Api/DTOs/Languages/LocalizedNameDto.cs rename to DTOs/Languages/LocalizedNameDto.cs index f88b4a6..34c064d 100644 --- a/Nop.Plugin.Api/DTOs/Languages/LocalizedNameDto.cs +++ b/DTOs/Languages/LocalizedNameDto.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Languages +namespace Nop.Plugin.Api.DTO.Languages { public class LocalizedNameDto { diff --git a/Nop.Plugin.Api/DTOs/Manufacturers/DiscountManufacturerMappingDto.cs b/DTOs/Manufacturers/DiscountManufacturerMappingDto.cs similarity index 87% rename from Nop.Plugin.Api/DTOs/Manufacturers/DiscountManufacturerMappingDto.cs rename to DTOs/Manufacturers/DiscountManufacturerMappingDto.cs index 7051ce9..85acbbb 100644 --- a/Nop.Plugin.Api/DTOs/Manufacturers/DiscountManufacturerMappingDto.cs +++ b/DTOs/Manufacturers/DiscountManufacturerMappingDto.cs @@ -1,9 +1,9 @@ using Newtonsoft.Json; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Discounts; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Manufacturers +namespace Nop.Plugin.Api.DTO.Manufacturers { [JsonObject(Title = "discount")] //[Validator(typeof(ProductDtoValidator))] diff --git a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturerDto.cs b/DTOs/Manufacturers/ManufacturerDto.cs similarity index 94% rename from Nop.Plugin.Api/DTOs/Manufacturers/ManufacturerDto.cs rename to DTOs/Manufacturers/ManufacturerDto.cs index 11a58fa..4e4b998 100644 --- a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturerDto.cs +++ b/DTOs/Manufacturers/ManufacturerDto.cs @@ -1,16 +1,14 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.Validators; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Languages; using System; using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.Manufacturers +namespace Nop.Plugin.Api.DTO.Manufacturers { [JsonObject(Title = "manufacturer")] - [Validator(typeof(ManufacturerDtoValidator))] + //[Validator(typeof(ManufacturerDtoValidator))] public class ManufacturerDto : BaseDto { private ImageDto _imageDto; diff --git a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersCountRootObject.cs b/DTOs/Manufacturers/ManufacturersCountRootObject.cs similarity index 78% rename from Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersCountRootObject.cs rename to DTOs/Manufacturers/ManufacturersCountRootObject.cs index 311fc40..10cbeb8 100644 --- a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersCountRootObject.cs +++ b/DTOs/Manufacturers/ManufacturersCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Manufacturers +namespace Nop.Plugin.Api.DTO.Manufacturers { public class ManufacturersCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersRootObject.cs b/DTOs/Manufacturers/ManufacturersRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersRootObject.cs rename to DTOs/Manufacturers/ManufacturersRootObject.cs index b264a77..7ab5005 100644 --- a/Nop.Plugin.Api/DTOs/Manufacturers/ManufacturersRootObject.cs +++ b/DTOs/Manufacturers/ManufacturersRootObject.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.Manufacturers +namespace Nop.Plugin.Api.DTO.Manufacturers { public class ManufacturersRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs b/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs similarity index 89% rename from Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs rename to DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs index 3edfcdc..c363aef 100644 --- a/Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs +++ b/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs @@ -1,34 +1,34 @@ -using System; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; - -namespace Nop.Plugin.Api.DTOs.Categories -{ - [JsonObject(Title = "news_letter_subscription")] - public class NewsLetterSubscriptionDto : BaseDto - { - /// - /// Gets or sets the email - /// - [JsonProperty("email")] - public string Email { get; set; } - - /// - /// Gets or sets whether the subscription is active - /// - [JsonProperty("active")] - public bool Active { get; set; } - - /// - /// Gets or sets whether the subscription is active - /// - [JsonProperty("store_id")] - public int StoreId { get; set; } - - /// - /// Gets or sets created on utc date - /// - [JsonProperty("created_on_utc")] - public DateTime? CreatedOnUtc { get; set; } - } +using System; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; + +namespace Nop.Plugin.Api.DTO.Categories +{ + [JsonObject(Title = "news_letter_subscription")] + public class NewsLetterSubscriptionDto : BaseDto + { + /// + /// Gets or sets the email + /// + [JsonProperty("email")] + public string Email { get; set; } + + /// + /// Gets or sets whether the subscription is active + /// + [JsonProperty("active")] + public bool Active { get; set; } + + /// + /// Gets or sets whether the subscription is active + /// + [JsonProperty("store_id")] + public int StoreId { get; set; } + + /// + /// Gets or sets created on utc date + /// + [JsonProperty("created_on_utc")] + public DateTime? CreatedOnUtc { get; set; } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs b/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs similarity index 94% rename from Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs rename to DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs index 7a9b985..928bcb5 100644 --- a/Nop.Plugin.Api/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs +++ b/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Categories +namespace Nop.Plugin.Api.DTO.Categories { public class NewsLetterSubscriptionsRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemDto.cs b/DTOs/OrderItems/OrderItemDto.cs similarity index 94% rename from Nop.Plugin.Api/DTOs/OrderItems/OrderItemDto.cs rename to DTOs/OrderItems/OrderItemDto.cs index f6bc3d8..1c5c0d6 100644 --- a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemDto.cs +++ b/DTOs/OrderItems/OrderItemDto.cs @@ -1,15 +1,14 @@ -using System; -using System.Collections.Generic; -using FluentValidation.Attributes; -using Newtonsoft.Json; +using Newtonsoft.Json; using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Products; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Products; using Nop.Plugin.Api.Validators; +using System; +using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.OrderItems +namespace Nop.Plugin.Api.DTO.OrderItems { - [Validator(typeof(OrderItemDtoValidator))] + //[Validator(typeof(OrderItemDtoValidator))] [JsonObject(Title = "order_item")] public class OrderItemDto : BaseDto { diff --git a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemsCountRootObject.cs b/DTOs/OrderItems/OrderItemsCountRootObject.cs similarity index 79% rename from Nop.Plugin.Api/DTOs/OrderItems/OrderItemsCountRootObject.cs rename to DTOs/OrderItems/OrderItemsCountRootObject.cs index c86212a..546b77d 100644 --- a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemsCountRootObject.cs +++ b/DTOs/OrderItems/OrderItemsCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.OrderItems +namespace Nop.Plugin.Api.DTO.OrderItems { public class OrderItemsCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemsRootObject.cs b/DTOs/OrderItems/OrderItemsRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/OrderItems/OrderItemsRootObject.cs rename to DTOs/OrderItems/OrderItemsRootObject.cs index c6eba59..881a06b 100644 --- a/Nop.Plugin.Api/DTOs/OrderItems/OrderItemsRootObject.cs +++ b/DTOs/OrderItems/OrderItemsRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.OrderItems +namespace Nop.Plugin.Api.DTO.OrderItems { public class OrderItemsRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Orders/OrderDto.cs b/DTOs/Orders/OrderDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Orders/OrderDto.cs rename to DTOs/Orders/OrderDto.cs index 317853a..9e51854 100644 --- a/Nop.Plugin.Api/DTOs/Orders/OrderDto.cs +++ b/DTOs/Orders/OrderDto.cs @@ -1,19 +1,19 @@ -using System; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.DTO.Shipments; +using System; using System.Collections.Generic; -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.Validators; - -namespace Nop.Plugin.Api.DTOs.Orders + +namespace Nop.Plugin.Api.DTO.Orders { [JsonObject(Title = "order")] - [Validator(typeof(OrderDtoValidator))] + //[Validator(typeof(OrderDtoValidator))] public class OrderDto : BaseDto { private ICollection _orderItems; + private ICollection _shipments; [JsonProperty("store_id")] public int? StoreId { get; set; } @@ -273,6 +273,21 @@ public ICollection OrderItems set { _orderItems = value; } } + [JsonProperty("shipments")] + public ICollection Shipments + { + get + { + if (_shipments == null) + { + _shipments = new List(); + } + + return _shipments; + } + set { _shipments = value; } + } + /// /// Gets or sets the order status /// diff --git a/Nop.Plugin.Api/DTOs/Orders/OrdersCountRootObject.cs b/DTOs/Orders/OrdersCountRootObject.cs similarity index 80% rename from Nop.Plugin.Api/DTOs/Orders/OrdersCountRootObject.cs rename to DTOs/Orders/OrdersCountRootObject.cs index 0d0544a..1288a9c 100644 --- a/Nop.Plugin.Api/DTOs/Orders/OrdersCountRootObject.cs +++ b/DTOs/Orders/OrdersCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Orders +namespace Nop.Plugin.Api.DTO.Orders { public class OrdersCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/Orders/OrdersRootObject.cs b/DTOs/Orders/OrdersRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Orders/OrdersRootObject.cs rename to DTOs/Orders/OrdersRootObject.cs index a08f28e..95f27eb 100644 --- a/Nop.Plugin.Api/DTOs/Orders/OrdersRootObject.cs +++ b/DTOs/Orders/OrdersRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Orders +namespace Nop.Plugin.Api.DTO.Orders { public class OrdersRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Orders/SingleOrderRootObject.cs b/DTOs/Orders/SingleOrderRootObject.cs similarity index 80% rename from Nop.Plugin.Api/DTOs/Orders/SingleOrderRootObject.cs rename to DTOs/Orders/SingleOrderRootObject.cs index 5bb4c2f..5260a0c 100644 --- a/Nop.Plugin.Api/DTOs/Orders/SingleOrderRootObject.cs +++ b/DTOs/Orders/SingleOrderRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Orders +namespace Nop.Plugin.Api.DTO.Orders { public class SingleOrderRootObject { diff --git a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributeDto.cs b/DTOs/ProductAttributes/ProductAttributeDto.cs similarity index 81% rename from Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributeDto.cs rename to DTOs/ProductAttributes/ProductAttributeDto.cs index 30202d9..b2ccdd5 100644 --- a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributeDto.cs +++ b/DTOs/ProductAttributes/ProductAttributeDto.cs @@ -1,12 +1,11 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; using Nop.Plugin.Api.Validators; -namespace Nop.Plugin.Api.DTOs.ProductAttributes +namespace Nop.Plugin.Api.DTO.ProductAttributes { [JsonObject(Title = "product_attribute")] - [Validator(typeof(ProductAttributeDtoValidator))] + //[Validator(typeof(ProductAttributeDtoValidator))] public class ProductAttributeDto : BaseDto { /// diff --git a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs b/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs similarity index 77% rename from Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs rename to DTOs/ProductAttributes/ProductAttributesCountRootObject.cs index 64779ac..e8eb9a4 100644 --- a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs +++ b/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ProductAttributes +namespace Nop.Plugin.Api.DTO.ProductAttributes { public class ProductAttributesCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs b/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs rename to DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs index ff6a93f..1ea3b70 100644 --- a/Nop.Plugin.Api/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs +++ b/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ProductAttributes +namespace Nop.Plugin.Api.DTO.ProductAttributes { public class ProductAttributesRootObjectDto : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs b/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs similarity index 75% rename from Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs rename to DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs index 11ab458..fabd80d 100644 --- a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs +++ b/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ProductCategoryMappings +namespace Nop.Plugin.Api.DTO.ProductCategoryMappings { public class ProductCategoryMappingsCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs b/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs similarity index 78% rename from Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs rename to DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs index b36aaeb..74c65ff 100644 --- a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs +++ b/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs @@ -1,12 +1,10 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.Validators; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.ProductCategoryMappings +namespace Nop.Plugin.Api.DTO.ProductCategoryMappings { [JsonObject(Title = "product_category_mapping")] - [Validator(typeof(ProductCategoryMappingDtoValidator))] + //[Validator(typeof(ProductCategoryMappingDtoValidator))] public class ProductCategoryMappingDto : BaseDto { /// diff --git a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs b/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs rename to DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs index 993e4d6..e3a635c 100644 --- a/Nop.Plugin.Api/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs +++ b/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ProductCategoryMappings +namespace Nop.Plugin.Api.DTO.ProductCategoryMappings { public class ProductCategoryMappingsRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/ProductItemAttributeDto.cs b/DTOs/ProductItemAttributeDto.cs similarity index 76% rename from Nop.Plugin.Api/DTOs/ProductItemAttributeDto.cs rename to DTOs/ProductItemAttributeDto.cs index e6d5f36..c0770f4 100644 --- a/Nop.Plugin.Api/DTOs/ProductItemAttributeDto.cs +++ b/DTOs/ProductItemAttributeDto.cs @@ -1,7 +1,7 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs +namespace Nop.Plugin.Api.DTO { [JsonObject(Title = "attribute")] public class ProductItemAttributeDto : BaseDto diff --git a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs similarity index 74% rename from Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs rename to DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs index 19bcf87..daf4af5 100644 --- a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs +++ b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ProductManufacturerMappings +namespace Nop.Plugin.Api.DTO.ProductManufacturerMappings { public class ProductManufacturerMappingsCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs similarity index 81% rename from Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs rename to DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs index 233664f..a121998 100644 --- a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs +++ b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsDto.cs @@ -1,12 +1,11 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; using Nop.Plugin.Api.Validators; -namespace Nop.Plugin.Api.DTOs.ProductManufacturerMappings +namespace Nop.Plugin.Api.DTO.ProductManufacturerMappings { [JsonObject(Title = "product_manufacturer_mapping")] - [Validator(typeof(ProductManufacturerMappingDtoValidator))] + //[Validator(typeof(ProductManufacturerMappingDtoValidator))] public class ProductManufacturerMappingsDto : BaseDto { /// diff --git a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs rename to DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs index 6b5ac59..66b886b 100644 --- a/Nop.Plugin.Api/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs +++ b/DTOs/ProductManufacturerMappings/ProductManufacturerMappingsRootObject.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.ProductManufacturerMappings +namespace Nop.Plugin.Api.DTO.ProductManufacturerMappings { public class ProductManufacturerMappingsRootObject : ISerializableObject { diff --git a/DTOs/ProductPictures/ProductPicturesRootObjectDto.cs b/DTOs/ProductPictures/ProductPicturesRootObjectDto.cs new file mode 100644 index 0000000..c21cc62 --- /dev/null +++ b/DTOs/ProductPictures/ProductPicturesRootObjectDto.cs @@ -0,0 +1,31 @@ + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Products; + +namespace Nop.Plugin.Api.DTO.ProductImages +{ + public class ProductPicturesRootObjectDto : ISerializableObject + { + public ProductPicturesRootObjectDto() + { + //Image = new ProductPicture(); + } + + [JsonProperty("image")] + public ImageMappingDto Image { get; set; } + + public string GetPrimaryPropertyName() + { + return "image"; + } + + public Type GetPrimaryPropertyType() + { + return typeof (ImageMappingDto); + } + } +} \ No newline at end of file diff --git a/Nop.Plugin.Api/DTOs/Products/ProductAttributeCombinationDto.cs b/DTOs/Products/ProductAttributeCombinationDto.cs similarity index 89% rename from Nop.Plugin.Api/DTOs/Products/ProductAttributeCombinationDto.cs rename to DTOs/Products/ProductAttributeCombinationDto.cs index 810db7d..19d5de2 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductAttributeCombinationDto.cs +++ b/DTOs/Products/ProductAttributeCombinationDto.cs @@ -1,12 +1,10 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.Validators; +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Products +namespace Nop.Plugin.Api.DTO.Products { [JsonObject(Title = "product_attribute_combination")] - [Validator(typeof(ProductAttributeCombinationDtoValidator))] + //[Validator(typeof(ProductAttributeCombinationDtoValidator))] public class ProductAttributeCombinationDto : BaseDto { /// diff --git a/Nop.Plugin.Api/DTOs/Products/ProductAttributeMappingDto.cs b/DTOs/Products/ProductAttributeMappingDto.cs similarity index 97% rename from Nop.Plugin.Api/DTOs/Products/ProductAttributeMappingDto.cs rename to DTOs/Products/ProductAttributeMappingDto.cs index 48f9db3..254c9b2 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductAttributeMappingDto.cs +++ b/DTOs/Products/ProductAttributeMappingDto.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using Newtonsoft.Json; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Products +namespace Nop.Plugin.Api.DTO.Products { [JsonObject(Title = "attribute")] //[Validator(typeof(ProductDtoValidator))] diff --git a/Nop.Plugin.Api/DTOs/Products/ProductAttributeValueDto.cs b/DTOs/Products/ProductAttributeValueDto.cs similarity index 97% rename from Nop.Plugin.Api/DTOs/Products/ProductAttributeValueDto.cs rename to DTOs/Products/ProductAttributeValueDto.cs index b8b0971..a578765 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductAttributeValueDto.cs +++ b/DTOs/Products/ProductAttributeValueDto.cs @@ -1,10 +1,10 @@ using System; using Newtonsoft.Json; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Images; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Images; -namespace Nop.Plugin.Api.DTOs.Products +namespace Nop.Plugin.Api.DTO.Products { [JsonObject(Title = "attribute_value")] //[Validator(typeof(ProductDtoValidator))] diff --git a/Nop.Plugin.Api/DTOs/Products/ProductDto.cs b/DTOs/Products/ProductDto.cs similarity index 95% rename from Nop.Plugin.Api/DTOs/Products/ProductDto.cs rename to DTOs/Products/ProductDto.cs index 406d469..2cfec55 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductDto.cs +++ b/DTOs/Products/ProductDto.cs @@ -1,654 +1,665 @@ -using System; -using System.Collections.Generic; -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.Base; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; -using Nop.Plugin.Api.Validators; - -namespace Nop.Plugin.Api.DTOs.Products -{ - [JsonObject(Title = "product")] - [Validator(typeof(ProductDtoValidator))] - public class ProductDto : BaseDto - { - private int? _productTypeId; - private List _storeIds; - private List _discountIds; - private List _roleIds; - private List _manufacturerIds; - private List _localizedNames; - private List _images; - private List _productAttributeMappings; - private List _productAttributeCombinations; - private List _productSpecificationAttributes; - private List _associatedProductIds; - private List _tags; - - /// - /// Gets or sets the values indicating whether this product is visible in catalog or search results. - /// It's used when this product is associated to some "grouped" one - /// This way associated products could be accessed/added/etc only from a grouped product details page - /// - [JsonProperty("visible_individually")] - public bool? VisibleIndividually { get; set; } - - /// - /// Gets or sets the name - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Gets or sets the localized names - /// - [JsonProperty("localized_names")] - public List LocalizedNames - { - get - { - return _localizedNames; - } - set - { - _localizedNames = value; - } - } - - /// - /// Gets or sets the short description - /// - [JsonProperty("short_description")] - public string ShortDescription { get; set; } - /// - /// Gets or sets the full description - /// - [JsonProperty("full_description")] - public string FullDescription { get; set; } - - /// - /// Gets or sets a value indicating whether to show the product on home page - /// - [JsonProperty("show_on_home_page")] - public bool? ShowOnHomePage { get; set; } - - /// - /// Gets or sets the meta keywords - /// - [JsonProperty("meta_keywords")] - public string MetaKeywords { get; set; } - /// - /// Gets or sets the meta description - /// - [JsonProperty("meta_description")] - public string MetaDescription { get; set; } - /// - /// Gets or sets the meta title - /// - [JsonProperty("meta_title")] - public string MetaTitle { get; set; } - - /// - /// Gets or sets a value indicating whether the product allows customer reviews - /// - [JsonProperty("allow_customer_reviews")] - public bool? AllowCustomerReviews { get; set; } - /// - /// Gets or sets the rating sum (approved reviews) - /// - [JsonProperty("approved_rating_sum")] - public int? ApprovedRatingSum { get; set; } - /// - /// Gets or sets the rating sum (not approved reviews) - /// - [JsonProperty("not_approved_rating_sum")] - public int? NotApprovedRatingSum { get; set; } - /// - /// Gets or sets the total rating votes (approved reviews) - /// - [JsonProperty("approved_total_reviews")] - public int? ApprovedTotalReviews { get; set; } - /// - /// Gets or sets the total rating votes (not approved reviews) - /// - [JsonProperty("not_approved_total_reviews")] - public int? NotApprovedTotalReviews { get; set; } - - /// - /// Gets or sets the SKU - /// - [JsonProperty("sku")] - public string Sku { get; set; } - /// - /// Gets or sets the manufacturer part number - /// - [JsonProperty("manufacturer_part_number")] - public string ManufacturerPartNumber { get; set; } - /// - /// Gets or sets the Global Trade Item Number (GTIN). These identifiers include UPC (in North America), EAN (in Europe), JAN (in Japan), and ISBN (for books). - /// - [JsonProperty("gtin")] - public string Gtin { get; set; } - - /// - /// Gets or sets a value indicating whether the product is gift card - /// - [JsonProperty("is_gift_card")] - public bool? IsGiftCard { get; set; } - - /// - /// Gets or sets a value indicating whether the product requires that other products are added to the cart (Product X requires Product Y) - /// - [JsonProperty("require_other_products")] - public bool? RequireOtherProducts { get; set; } - - /// - /// Gets or sets a value indicating whether required products are automatically added to the cart - /// - [JsonProperty("automatically_add_required_products")] - public bool? AutomaticallyAddRequiredProducts { get; set; } - - /// - /// Gets or sets a value indicating whether the product is download - /// - [JsonProperty("is_download")] - public bool? IsDownload { get; set; } - - /// - /// Gets or sets a value indicating whether this downloadable product can be downloaded unlimited number of times - /// - [JsonProperty("unlimited_downloads")] - public bool? UnlimitedDownloads { get; set; } - /// - /// Gets or sets the maximum number of downloads - /// - [JsonProperty("max_number_of_downloads")] - public int? MaxNumberOfDownloads { get; set; } - /// - /// Gets or sets the number of days during customers keeps access to the file. - /// - [JsonProperty("download_expiration_days")] - public int? DownloadExpirationDays { get; set; } - - /// - /// Gets or sets a value indicating whether the product has a sample download file - /// - [JsonProperty("has_sample_download")] - public bool? HasSampleDownload { get; set; } - - /// - /// Gets or sets a value indicating whether the product has user agreement - /// - [JsonProperty("has_user_agreement")] - public bool? HasUserAgreement { get; set; } - - /// - /// Gets or sets a value indicating whether the product is recurring - /// - [JsonProperty("is_recurring")] - public bool? IsRecurring { get; set; } - /// - /// Gets or sets the cycle length - /// - [JsonProperty("recurring_cycle_length")] - public int? RecurringCycleLength { get; set; } - - /// - /// Gets or sets the total cycles - /// - [JsonProperty("recurring_total_cycles")] - public int? RecurringTotalCycles { get; set; } - - /// - /// Gets or sets a value indicating whether the product is rental - /// - [JsonProperty("is_rental")] - public bool? IsRental { get; set; } - /// - /// Gets or sets the rental length for some period (price for this period) - /// - [JsonProperty("rental_price_length")] - public int? RentalPriceLength { get; set; } - - /// - /// Gets or sets a value indicating whether the entity is ship enabled - /// - [JsonProperty("is_ship_enabled")] - public bool? IsShipEnabled { get; set; } - /// - /// Gets or sets a value indicating whether the entity is free shipping - /// - [JsonProperty("is_free_shipping")] - public bool? IsFreeShipping { get; set; } - /// - /// Gets or sets a value this product should be shipped separately (each item) - /// - [JsonProperty("ship_separately")] - public bool? ShipSeparately { get; set; } - /// - /// Gets or sets the additional shipping charge - /// - [JsonProperty("additional_shipping_charge")] - public decimal? AdditionalShippingCharge { get; set; } - - /// - /// Gets or sets a value indicating whether the product is marked as tax exempt - /// - [JsonProperty("is_tax_exempt")] - public bool? IsTaxExempt { get; set; } - - /// - /// Gets or sets a value indicating whether the product is telecommunications or broadcasting or electronic services - /// - [JsonProperty("is_telecommunications_or_broadcasting_or_electronic_services")] - public bool? IsTelecommunicationsOrBroadcastingOrElectronicServices { get; set; } - - /// - /// Gets or sets a value indicating whether multiple warehouses are used for this product - /// - [JsonProperty("use_multiple_warehouses")] - public bool? UseMultipleWarehouses { get; set; } - - /// - /// Gets or sets a value indicating how to manage inventory. - /// 0 - do not track inventory - /// 1 - track inventory - /// 2 - track invetory by attributes - /// - [JsonProperty("manage_inventory_method_id")] - public int? ManageInventoryMethodId { get; set; } - - /// - /// Gets or sets the stock quantity - /// - [JsonProperty("stock_quantity")] - public int? StockQuantity { get; set; } - /// - /// Gets or sets a value indicating whether to display stock availability - /// - [JsonProperty("display_stock_availability")] - public bool? DisplayStockAvailability { get; set; } - /// - /// Gets or sets a value indicating whether to display stock quantity - /// - [JsonProperty("display_stock_quantity")] - public bool? DisplayStockQuantity { get; set; } - /// - /// Gets or sets the minimum stock quantity - /// - [JsonProperty("min_stock_quantity")] - public int? MinStockQuantity { get; set; } - - /// - /// Gets or sets the quantity when admin should be notified - /// - [JsonProperty("notify_admin_for_quantity_below")] - public int? NotifyAdminForQuantityBelow { get; set; } - - /// - /// Gets or sets a value indicating whether to back in stock subscriptions are allowed - /// - [JsonProperty("allow_back_in_stock_subscriptions")] - public bool? AllowBackInStockSubscriptions { get; set; } - /// - /// Gets or sets the order minimum quantity - /// - [JsonProperty("order_minimum_quantity")] - public int? OrderMinimumQuantity { get; set; } - /// - /// Gets or sets the order maximum quantity - /// - [JsonProperty("order_maximum_quantity")] - public int? OrderMaximumQuantity { get; set; } - /// - /// Gets or sets the comma seperated list of allowed quantities. null or empty if any quantity is allowed - /// - [JsonProperty("allowed_quantities")] - public string AllowedQuantities { get; set; } - /// - /// Gets or sets a value indicating whether we allow adding to the cart/wishlist only attribute combinations that exist and have stock greater than zero. - /// This option is used only when we have "manage inventory" set to "track inventory by product attributes" - /// - [JsonProperty("allow_adding_only_existing_attribute_combinations")] - public bool? AllowAddingOnlyExistingAttributeCombinations { get; set; } - - /// - /// Gets or sets a value indicating whether to disable buy (Add to cart) button - /// - [JsonProperty("disable_buy_button")] - public bool? DisableBuyButton { get; set; } - /// - /// Gets or sets a value indicating whether to disable "Add to wishlist" button - /// - [JsonProperty("disable_wishlist_button")] - public bool? DisableWishlistButton { get; set; } - /// - /// Gets or sets a value indicating whether this item is available for Pre-Order - /// - [JsonProperty("available_for_pre_order")] - public bool? AvailableForPreOrder { get; set; } - /// - /// Gets or sets the start date and time of the product availability (for pre-order products) - /// - [JsonProperty("pre_order_availability_start_date_time_utc")] - public DateTime? PreOrderAvailabilityStartDateTimeUtc { get; set; } - /// - /// Gets or sets a value indicating whether to show "Call for Pricing" or "Call for quote" instead of price - /// - [JsonProperty("call_for_price")] - public bool? CallForPrice { get; set; } - /// - /// Gets or sets the price - /// - [JsonProperty("price")] - public decimal? Price { get; set; } - /// - /// Gets or sets the old price - /// - [JsonProperty("old_price")] - public decimal? OldPrice { get; set; } - /// - /// Gets or sets the product cost - /// - [JsonProperty("product_cost")] - public decimal? ProductCost { get; set; } - /// - /// Gets or sets the product special price - /// - [JsonProperty("special_price")] - public decimal? SpecialPrice { get; set; } - /// - /// Gets or sets the start date and time of the special price - /// - [JsonProperty("special_price_start_date_time_utc")] - public DateTime? SpecialPriceStartDateTimeUtc { get; set; } - /// - /// Gets or sets the end date and time of the special price - /// - [JsonProperty("special_price_end_date_time_utc")] - public DateTime? SpecialPriceEndDateTimeUtc { get; set; } - /// - /// Gets or sets a value indicating whether a customer enters price - /// - [JsonProperty("customer_enters_price")] - public bool? CustomerEntersPrice { get; set; } - /// - /// Gets or sets the minimum price entered by a customer - /// - [JsonProperty("minimum_customer_entered_price")] - public decimal? MinimumCustomerEnteredPrice { get; set; } - /// - /// Gets or sets the maximum price entered by a customer - /// - [JsonProperty("maximum_customer_entered_price")] - public decimal? MaximumCustomerEnteredPrice { get; set; } - - /// - /// Gets or sets a value indicating whether base price (PAngV) is enabled. Used by German users. - /// - [JsonProperty("baseprice_enabled")] - public bool? BasepriceEnabled { get; set; } - /// - /// Gets or sets an amount in product for PAngV - /// - [JsonProperty("baseprice_amount")] - public decimal? BasepriceAmount { get; set; } - - /// - /// Gets or sets a reference amount for PAngV - /// - [JsonProperty("baseprice_base_amount")] - public decimal? BasepriceBaseAmount { get; set; } - - /// - /// Gets or sets a value indicating whether this product has tier prices configured - /// The same as if we run this.TierPrices.Count > 0 - /// We use this property for performance optimization: - /// if this property is set to false, then we do not need to load tier prices navigation property - /// - /// - [JsonProperty("has_tier_prices")] - public bool? HasTierPrices { get; set; } - /// - /// Gets or sets a value indicating whether this product has discounts applied - /// The same as if we run this.AppliedDiscounts.Count > 0 - /// We use this property for performance optimization: - /// if this property is set to false, then we do not need to load Applied Discounts navigation property - /// - /// - [JsonProperty("has_discounts_applied")] - public bool? HasDiscountsApplied { get; set; } - - /// - /// Gets or sets the weight - /// - [JsonProperty("weight")] - public decimal? Weight { get; set; } - /// - /// Gets or sets the length - /// - [JsonProperty("length")] - public decimal? Length { get; set; } - /// - /// Gets or sets the width - /// - [JsonProperty("width")] - public decimal? Width { get; set; } - /// - /// Gets or sets the height - /// - [JsonProperty("height")] - public decimal? Height { get; set; } - - /// - /// Gets or sets the available start date and time - /// - [JsonProperty("available_start_date_time_utc")] - public DateTime? AvailableStartDateTimeUtc { get; set; } - /// - /// Gets or sets the available end date and time - /// - [JsonProperty("available_end_date_time_utc")] - public DateTime? AvailableEndDateTimeUtc { get; set; } - - /// - /// Gets or sets a display order. - /// This value is used when sorting associated products (used with "grouped" products) - /// This value is used when sorting home page products - /// - [JsonProperty("display_order")] - public int? DisplayOrder { get; set; } - /// - /// Gets or sets a value indicating whether the entity is published - /// - [JsonProperty("published")] - public bool? Published { get; set; } - /// - /// Gets or sets a value indicating whether the entity has been deleted - /// - [JsonProperty("deleted")] - public bool? Deleted { get; set; } - - /// - /// Gets or sets the date and time of product creation - /// - [JsonProperty("created_on_utc")] - public DateTime? CreatedOnUtc { get; set; } - /// - /// Gets or sets the date and time of product update - /// - [JsonProperty("updated_on_utc")] - public DateTime? UpdatedOnUtc { get; set; } - - /// - /// Gets or sets the product type - /// - [ProductTypeValidationAttribute] - [JsonProperty("product_type")] - public string ProductType - { - get - { - var productTypeId = this._productTypeId; - if (productTypeId != null) return ((ProductType)productTypeId).ToString(); - - return null; - } - set - { - ProductType productTypeId; - if (Enum.TryParse(value, out productTypeId)) - { - this._productTypeId = (int)productTypeId; - } - else this._productTypeId = null; - } - } - - [JsonProperty("parent_grouped_product_id")] - public int? ParentGroupedProductId { get; set; } - - [JsonProperty("role_ids")] - public List RoleIds - { - get - { - return _roleIds; - } - set - { - _roleIds = value; - } - } - - [JsonProperty("discount_ids")] - public List DiscountIds - { - get - { - return _discountIds; - } - set - { - _discountIds = value; - } - } - - [JsonProperty("store_ids")] - public List StoreIds - { - get - { - return _storeIds; - } - set - { - _storeIds = value; - } - } - - [JsonProperty("manufacturer_ids")] - public List ManufacturerIds - { - get - { - return _manufacturerIds; - } - set - { - _manufacturerIds = value; - } - } - - [ImageCollectionValidation] - [JsonProperty("images")] - public List Images - { - get - { - return _images; - } - set - { - _images = value; - } - } - - [JsonProperty("attributes")] - public List ProductAttributeMappings - { - get - { - return _productAttributeMappings; - } - set - { - _productAttributeMappings = value; - } - } - - [JsonProperty("product_attribute_combinations")] - public List ProductAttributeCombinations - { - get - { - return _productAttributeCombinations; - } - set - { - _productAttributeCombinations = value; - } - } - - - [JsonProperty("product_specification_attributes")] - public List ProductSpecificationAttributes - { - get - { - return _productSpecificationAttributes; - } - set - { - _productSpecificationAttributes = value; - } - } - - [JsonProperty("associated_product_ids")] - public List AssociatedProductIds - { - get - { - return _associatedProductIds; - } - set - { - _associatedProductIds = value; - } - } - - [JsonProperty("tags")] - public List Tags - { - get - { - return _tags; - } - set - { - _tags = value; - } - } - - [ValidateVendor] - [JsonProperty("vendor_id")] - public int? VendorId { get; set; } - - [JsonProperty("se_name")] - public string SeName { get; set; } - } +using Newtonsoft.Json; +using Nop.Core.Domain.Catalog; +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Languages; +using Nop.Plugin.Api.DTO.SpecificationAttributes; +using System; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.DTO.Products +{ + [JsonObject(Title = "product")] + //[Validator(typeof(ProductDtoValidator))] + public class ProductDto : BaseDto + { + private int? _productTypeId; + private List _storeIds; + private List _discountIds; + private List _roleIds; + private List _manufacturerIds; + private List _localizedNames; + private List _images; + private List _productAttributeMappings; + private List _productAttributeCombinations; + private List _productSpecificationAttributes; + private List _associatedProductIds; + private List _tags; + + /// + /// Gets or sets the values indicating whether this product is visible in catalog or search results. + /// It's used when this product is associated to some "grouped" one + /// This way associated products could be accessed/added/etc only from a grouped product details page + /// + [JsonProperty("visible_individually")] + public bool? VisibleIndividually { get; set; } + + /// + /// Gets or sets the name + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Gets or sets the localized names + /// + [JsonProperty("localized_names")] + public List LocalizedNames + { + get + { + return _localizedNames; + } + set + { + _localizedNames = value; + } + } + + /// + /// Gets or sets the short description + /// + [JsonProperty("short_description")] + public string ShortDescription { get; set; } + /// + /// Gets or sets the full description + /// + [JsonProperty("full_description")] + public string FullDescription { get; set; } + + /// + /// Gets or sets a value indicating whether to show the product on home page + /// + [JsonProperty("show_on_home_page")] + public bool? ShowOnHomePage { get; set; } + + /// + /// Gets or sets the meta keywords + /// + [JsonProperty("meta_keywords")] + public string MetaKeywords { get; set; } + /// + /// Gets or sets the meta description + /// + [JsonProperty("meta_description")] + public string MetaDescription { get; set; } + /// + /// Gets or sets the meta title + /// + [JsonProperty("meta_title")] + public string MetaTitle { get; set; } + + /// + /// Gets or sets a value indicating whether the product allows customer reviews + /// + [JsonProperty("allow_customer_reviews")] + public bool? AllowCustomerReviews { get; set; } + /// + /// Gets or sets the rating sum (approved reviews) + /// + [JsonProperty("approved_rating_sum")] + public int? ApprovedRatingSum { get; set; } + /// + /// Gets or sets the rating sum (not approved reviews) + /// + [JsonProperty("not_approved_rating_sum")] + public int? NotApprovedRatingSum { get; set; } + /// + /// Gets or sets the total rating votes (approved reviews) + /// + [JsonProperty("approved_total_reviews")] + public int? ApprovedTotalReviews { get; set; } + /// + /// Gets or sets the total rating votes (not approved reviews) + /// + [JsonProperty("not_approved_total_reviews")] + public int? NotApprovedTotalReviews { get; set; } + + /// + /// Gets or sets the SKU + /// + [JsonProperty("sku")] + public string Sku { get; set; } + /// + /// Gets or sets the manufacturer part number + /// + [JsonProperty("manufacturer_part_number")] + public string ManufacturerPartNumber { get; set; } + /// + /// Gets or sets the Global Trade Item Number (GTIN). These identifiers include UPC (in North America), EAN (in Europe), JAN (in Japan), and ISBN (for books). + /// + [JsonProperty("gtin")] + public string Gtin { get; set; } + + /// + /// Gets or sets a value indicating whether the product is gift card + /// + [JsonProperty("is_gift_card")] + public bool? IsGiftCard { get; set; } + + /// + /// Gets or sets a value indicating whether the product requires that other products are added to the cart (Product X requires Product Y) + /// + [JsonProperty("require_other_products")] + public bool? RequireOtherProducts { get; set; } + + /// + /// Gets or sets a value indicating whether required products are automatically added to the cart + /// + [JsonProperty("automatically_add_required_products")] + public bool? AutomaticallyAddRequiredProducts { get; set; } + + /// + /// Gets or sets a value indicating whether the product is download + /// + [JsonProperty("is_download")] + public bool? IsDownload { get; set; } + + /// + /// Gets or sets a value indicating whether this downloadable product can be downloaded unlimited number of times + /// + [JsonProperty("unlimited_downloads")] + public bool? UnlimitedDownloads { get; set; } + /// + /// Gets or sets the maximum number of downloads + /// + [JsonProperty("max_number_of_downloads")] + public int? MaxNumberOfDownloads { get; set; } + /// + /// Gets or sets the number of days during customers keeps access to the file. + /// + [JsonProperty("download_expiration_days")] + public int? DownloadExpirationDays { get; set; } + + /// + /// Gets or sets a value indicating whether the product has a sample download file + /// + [JsonProperty("has_sample_download")] + public bool? HasSampleDownload { get; set; } + + /// + /// Gets or sets a value indicating whether the product has user agreement + /// + [JsonProperty("has_user_agreement")] + public bool? HasUserAgreement { get; set; } + + /// + /// Gets or sets a value indicating whether the product is recurring + /// + [JsonProperty("is_recurring")] + public bool? IsRecurring { get; set; } + /// + /// Gets or sets the cycle length + /// + [JsonProperty("recurring_cycle_length")] + public int? RecurringCycleLength { get; set; } + + /// + /// Gets or sets the total cycles + /// + [JsonProperty("recurring_total_cycles")] + public int? RecurringTotalCycles { get; set; } + + /// + /// Gets or sets a value indicating whether the product is rental + /// + [JsonProperty("is_rental")] + public bool? IsRental { get; set; } + /// + /// Gets or sets the rental length for some period (price for this period) + /// + [JsonProperty("rental_price_length")] + public int? RentalPriceLength { get; set; } + + /// + /// Gets or sets a value indicating whether the entity is ship enabled + /// + [JsonProperty("is_ship_enabled")] + public bool? IsShipEnabled { get; set; } + /// + /// Gets or sets a value indicating whether the entity is free shipping + /// + [JsonProperty("is_free_shipping")] + public bool? IsFreeShipping { get; set; } + /// + /// Gets or sets a value this product should be shipped separately (each item) + /// + [JsonProperty("ship_separately")] + public bool? ShipSeparately { get; set; } + /// + /// Gets or sets the additional shipping charge + /// + [JsonProperty("additional_shipping_charge")] + public decimal? AdditionalShippingCharge { get; set; } + + /// + /// Gets or sets a value indicating whether the product is marked as tax exempt + /// + [JsonProperty("is_tax_exempt")] + public bool? IsTaxExempt { get; set; } + + + /// + /// Gets or sets the tax category identifier + /// + [JsonProperty("tax_category_id")] + public int TaxCategoryId { get; set; } + + /// + /// Gets or sets the backorder mode id + /// + [JsonProperty("backorder_mode_id")] + public int? BackorderModeId { get; set; } + + /// + /// Gets or sets a value indicating whether the product is telecommunications or broadcasting or electronic services + /// + [JsonProperty("is_telecommunications_or_broadcasting_or_electronic_services")] + public bool? IsTelecommunicationsOrBroadcastingOrElectronicServices { get; set; } + + /// + /// Gets or sets a value indicating whether multiple warehouses are used for this product + /// + [JsonProperty("use_multiple_warehouses")] + public bool? UseMultipleWarehouses { get; set; } + + /// + /// Gets or sets a value indicating how to manage inventory. + /// 0 - do not track inventory + /// 1 - track inventory + /// 2 - track invetory by attributes + /// + [JsonProperty("manage_inventory_method_id")] + public int? ManageInventoryMethodId { get; set; } + + /// + /// Gets or sets the stock quantity + /// + [JsonProperty("stock_quantity")] + public int? StockQuantity { get; set; } + /// + /// Gets or sets a value indicating whether to display stock availability + /// + [JsonProperty("display_stock_availability")] + public bool? DisplayStockAvailability { get; set; } + /// + /// Gets or sets a value indicating whether to display stock quantity + /// + [JsonProperty("display_stock_quantity")] + public bool? DisplayStockQuantity { get; set; } + /// + /// Gets or sets the minimum stock quantity + /// + [JsonProperty("min_stock_quantity")] + public int? MinStockQuantity { get; set; } + + /// + /// Gets or sets the quantity when admin should be notified + /// + [JsonProperty("notify_admin_for_quantity_below")] + public int? NotifyAdminForQuantityBelow { get; set; } + + /// + /// Gets or sets a value indicating whether to back in stock subscriptions are allowed + /// + [JsonProperty("allow_back_in_stock_subscriptions")] + public bool? AllowBackInStockSubscriptions { get; set; } + /// + /// Gets or sets the order minimum quantity + /// + [JsonProperty("order_minimum_quantity")] + public int? OrderMinimumQuantity { get; set; } + /// + /// Gets or sets the order maximum quantity + /// + [JsonProperty("order_maximum_quantity")] + public int? OrderMaximumQuantity { get; set; } + /// + /// Gets or sets the comma seperated list of allowed quantities. null or empty if any quantity is allowed + /// + [JsonProperty("allowed_quantities")] + public string AllowedQuantities { get; set; } + /// + /// Gets or sets a value indicating whether we allow adding to the cart/wishlist only attribute combinations that exist and have stock greater than zero. + /// This option is used only when we have "manage inventory" set to "track inventory by product attributes" + /// + [JsonProperty("allow_adding_only_existing_attribute_combinations")] + public bool? AllowAddingOnlyExistingAttributeCombinations { get; set; } + + /// + /// Gets or sets a value indicating whether to disable buy (Add to cart) button + /// + [JsonProperty("disable_buy_button")] + public bool? DisableBuyButton { get; set; } + /// + /// Gets or sets a value indicating whether to disable "Add to wishlist" button + /// + [JsonProperty("disable_wishlist_button")] + public bool? DisableWishlistButton { get; set; } + /// + /// Gets or sets a value indicating whether this item is available for Pre-Order + /// + [JsonProperty("available_for_pre_order")] + public bool? AvailableForPreOrder { get; set; } + /// + /// Gets or sets the start date and time of the product availability (for pre-order products) + /// + [JsonProperty("pre_order_availability_start_date_time_utc")] + public DateTime? PreOrderAvailabilityStartDateTimeUtc { get; set; } + /// + /// Gets or sets a value indicating whether to show "Call for Pricing" or "Call for quote" instead of price + /// + [JsonProperty("call_for_price")] + public bool? CallForPrice { get; set; } + /// + /// Gets or sets the price + /// + [JsonProperty("price")] + public decimal? Price { get; set; } + /// + /// Gets or sets the old price + /// + [JsonProperty("old_price")] + public decimal? OldPrice { get; set; } + /// + /// Gets or sets the product cost + /// + [JsonProperty("product_cost")] + public decimal? ProductCost { get; set; } + /// + /// Gets or sets the product special price + /// + [JsonProperty("special_price")] + public decimal? SpecialPrice { get; set; } + /// + /// Gets or sets the start date and time of the special price + /// + [JsonProperty("special_price_start_date_time_utc")] + public DateTime? SpecialPriceStartDateTimeUtc { get; set; } + /// + /// Gets or sets the end date and time of the special price + /// + [JsonProperty("special_price_end_date_time_utc")] + public DateTime? SpecialPriceEndDateTimeUtc { get; set; } + /// + /// Gets or sets a value indicating whether a customer enters price + /// + [JsonProperty("customer_enters_price")] + public bool? CustomerEntersPrice { get; set; } + /// + /// Gets or sets the minimum price entered by a customer + /// + [JsonProperty("minimum_customer_entered_price")] + public decimal? MinimumCustomerEnteredPrice { get; set; } + /// + /// Gets or sets the maximum price entered by a customer + /// + [JsonProperty("maximum_customer_entered_price")] + public decimal? MaximumCustomerEnteredPrice { get; set; } + + /// + /// Gets or sets a value indicating whether base price (PAngV) is enabled. Used by German users. + /// + [JsonProperty("baseprice_enabled")] + public bool? BasepriceEnabled { get; set; } + /// + /// Gets or sets an amount in product for PAngV + /// + [JsonProperty("baseprice_amount")] + public decimal? BasepriceAmount { get; set; } + + /// + /// Gets or sets a reference amount for PAngV + /// + [JsonProperty("baseprice_base_amount")] + public decimal? BasepriceBaseAmount { get; set; } + + /// + /// Gets or sets a value indicating whether this product has tier prices configured + /// The same as if we run this.TierPrices.Count > 0 + /// We use this property for performance optimization: + /// if this property is set to false, then we do not need to load tier prices navigation property + /// + /// + [JsonProperty("has_tier_prices")] + public bool? HasTierPrices { get; set; } + /// + /// Gets or sets a value indicating whether this product has discounts applied + /// The same as if we run this.AppliedDiscounts.Count > 0 + /// We use this property for performance optimization: + /// if this property is set to false, then we do not need to load Applied Discounts navigation property + /// + /// + [JsonProperty("has_discounts_applied")] + public bool? HasDiscountsApplied { get; set; } + + /// + /// Gets or sets the weight + /// + [JsonProperty("weight")] + public decimal? Weight { get; set; } + /// + /// Gets or sets the length + /// + [JsonProperty("length")] + public decimal? Length { get; set; } + /// + /// Gets or sets the width + /// + [JsonProperty("width")] + public decimal? Width { get; set; } + /// + /// Gets or sets the height + /// + [JsonProperty("height")] + public decimal? Height { get; set; } + + /// + /// Gets or sets the available start date and time + /// + [JsonProperty("available_start_date_time_utc")] + public DateTime? AvailableStartDateTimeUtc { get; set; } + /// + /// Gets or sets the available end date and time + /// + [JsonProperty("available_end_date_time_utc")] + public DateTime? AvailableEndDateTimeUtc { get; set; } + + /// + /// Gets or sets a display order. + /// This value is used when sorting associated products (used with "grouped" products) + /// This value is used when sorting home page products + /// + [JsonProperty("display_order")] + public int? DisplayOrder { get; set; } + /// + /// Gets or sets a value indicating whether the entity is published + /// + [JsonProperty("published")] + public bool? Published { get; set; } + /// + /// Gets or sets a value indicating whether the entity has been deleted + /// + [JsonProperty("deleted")] + public bool? Deleted { get; set; } + + /// + /// Gets or sets the date and time of product creation + /// + [JsonProperty("created_on_utc")] + public DateTime? CreatedOnUtc { get; set; } + /// + /// Gets or sets the date and time of product update + /// + [JsonProperty("updated_on_utc")] + public DateTime? UpdatedOnUtc { get; set; } + + /// + /// Gets or sets the product type + /// + [ProductTypeValidationAttribute] + [JsonProperty("product_type")] + public string ProductType + { + get + { + var productTypeId = this._productTypeId; + if (productTypeId != null) return ((ProductType)productTypeId).ToString(); + + return null; + } + set + { + ProductType productTypeId; + if (Enum.TryParse(value, out productTypeId)) + { + this._productTypeId = (int)productTypeId; + } + else this._productTypeId = null; + } + } + + [JsonProperty("parent_grouped_product_id")] + public int? ParentGroupedProductId { get; set; } + + [JsonProperty("role_ids")] + public List RoleIds + { + get + { + return _roleIds; + } + set + { + _roleIds = value; + } + } + + [JsonProperty("discount_ids")] + public List DiscountIds + { + get + { + return _discountIds; + } + set + { + _discountIds = value; + } + } + + [JsonProperty("store_ids")] + public List StoreIds + { + get + { + return _storeIds; + } + set + { + _storeIds = value; + } + } + + [JsonProperty("manufacturer_ids")] + public List ManufacturerIds + { + get + { + return _manufacturerIds; + } + set + { + _manufacturerIds = value; + } + } + + [ImageCollectionValidation] + [JsonProperty("images")] + public List Images + { + get + { + return _images; + } + set + { + _images = value; + } + } + + [JsonProperty("attributes")] + public List ProductAttributeMappings + { + get + { + return _productAttributeMappings; + } + set + { + _productAttributeMappings = value; + } + } + + [JsonProperty("product_attribute_combinations")] + public List ProductAttributeCombinations + { + get + { + return _productAttributeCombinations; + } + set + { + _productAttributeCombinations = value; + } + } + + + [JsonProperty("product_specification_attributes")] + public List ProductSpecificationAttributes + { + get + { + return _productSpecificationAttributes; + } + set + { + _productSpecificationAttributes = value; + } + } + + [JsonProperty("associated_product_ids")] + public List AssociatedProductIds + { + get + { + return _associatedProductIds; + } + set + { + _associatedProductIds = value; + } + } + + [JsonProperty("tags")] + public List Tags + { + get + { + return _tags; + } + set + { + _tags = value; + } + } + + [ValidateVendor] + [JsonProperty("vendor_id")] + public int? VendorId { get; set; } + + [JsonProperty("se_name")] + public string SeName { get; set; } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/DTOs/Products/ProductsCountRootObject.cs b/DTOs/Products/ProductsCountRootObject.cs similarity index 79% rename from Nop.Plugin.Api/DTOs/Products/ProductsCountRootObject.cs rename to DTOs/Products/ProductsCountRootObject.cs index 4730d4b..c3a2847 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductsCountRootObject.cs +++ b/DTOs/Products/ProductsCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Products +namespace Nop.Plugin.Api.DTO.Products { public class ProductsCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/Products/ProductsRootObjectDto.cs b/DTOs/Products/ProductsRootObjectDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Products/ProductsRootObjectDto.cs rename to DTOs/Products/ProductsRootObjectDto.cs index bfed84f..95b2848 100644 --- a/Nop.Plugin.Api/DTOs/Products/ProductsRootObjectDto.cs +++ b/DTOs/Products/ProductsRootObjectDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Products +namespace Nop.Plugin.Api.DTO.Products { public class ProductsRootObjectDto : ISerializableObject { diff --git a/DTOs/Shipments/ShipmentDto.cs b/DTOs/Shipments/ShipmentDto.cs new file mode 100644 index 0000000..f8a54df --- /dev/null +++ b/DTOs/Shipments/ShipmentDto.cs @@ -0,0 +1,46 @@ +using Nop.Plugin.Api.DTO.Base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Nop.Plugin.Api.DTO.Shipments +{ + public class ShipmentDto : BaseDto + { + /// + /// Gets or sets the order identifier + /// + public int OrderId { get; set; } + + /// + /// Gets or sets the tracking number of this shipment + /// + public string TrackingNumber { get; set; } + + /// + /// Gets or sets the total weight of this shipment + /// It's nullable for compatibility with the previous version of nopCommerce where was no such property + /// + public decimal? TotalWeight { get; set; } + + /// + /// Gets or sets the shipped date and time + /// + public DateTime? ShippedDateUtc { get; set; } + + /// + /// Gets or sets the delivery date and time + /// + public DateTime? DeliveryDateUtc { get; set; } + + /// + /// Gets or sets the admin comment + /// + public string AdminComment { get; set; } + + /// + /// Gets or sets the entity creation date + /// + public DateTime CreatedOnUtc { get; set; } + } +} diff --git a/Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemDto.cs b/DTOs/ShoppingCarts/ShoppingCartItemDto.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemDto.cs rename to DTOs/ShoppingCarts/ShoppingCartItemDto.cs index 9c992c0..f719ed8 100644 --- a/Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemDto.cs +++ b/DTOs/ShoppingCarts/ShoppingCartItemDto.cs @@ -1,16 +1,16 @@ -using System; -using FluentValidation.Attributes; -using Newtonsoft.Json; +using Newtonsoft.Json; using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.DTOs.Products; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.DTO; using Nop.Plugin.Api.Validators; +using System; using System.Collections.Generic; -using Nop.Plugin.Api.DTOs.Base; -namespace Nop.Plugin.Api.DTOs.ShoppingCarts +namespace Nop.Plugin.Api.DTO.ShoppingCarts { - [Validator(typeof(ShoppingCartItemDtoValidator))] + //[Validator(typeof(ShoppingCartItemDtoValidator))] [JsonObject(Title = "shopping_cart_item")] public class ShoppingCartItemDto : BaseDto { diff --git a/Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs b/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs rename to DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs index 4983112..3ed952a 100644 --- a/Nop.Plugin.Api/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs +++ b/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.ShoppingCarts +namespace Nop.Plugin.Api.DTO.ShoppingCarts { public class ShoppingCartItemsRootObject : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs b/DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs rename to DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs index 2d4ac17..0789949 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs +++ b/DTOs/SpecificationAttributes/ProductSpecificationAttributeDto.cs @@ -1,13 +1,12 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; +using Newtonsoft.Json; using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.Validators; using System; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { [JsonObject(Title = "product_specification_attribute")] - [Validator(typeof(ProductSpecificationAttributeDtoValidator))] + //[Validator(typeof(ProductSpecificationAttributeDtoValidator))] public class ProductSpecificationAttributeDto { /// diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs b/DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs similarity index 76% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs rename to DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs index 0cb3250..7898e5b 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs +++ b/DTOs/SpecificationAttributes/ProductSpecificationAttributesCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { public class ProductSpecificationAttributesCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs b/DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs rename to DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs index e4df467..f430d40 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs +++ b/DTOs/SpecificationAttributes/ProductSpecificationAttributesRootObjectDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { public class ProductSpecificationAttributesRootObjectDto : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeDto.cs b/DTOs/SpecificationAttributes/SpecificationAttributeDto.cs similarity index 85% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeDto.cs rename to DTOs/SpecificationAttributes/SpecificationAttributeDto.cs index 25e6daa..3c8480a 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeDto.cs +++ b/DTOs/SpecificationAttributes/SpecificationAttributeDto.cs @@ -1,12 +1,12 @@ -using FluentValidation.Attributes; +//using FluentValidation.Attributes; using Newtonsoft.Json; using Nop.Plugin.Api.Validators; using System.Collections.Generic; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { [JsonObject(Title = "specification_attribute")] - [Validator(typeof(SpecificationAttributeDtoValidator))] + //[Validator(typeof(SpecificationAttributeDtoValidator))] public class SpecificationAttributeDto { /// diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs b/DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs similarity index 83% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs rename to DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs index e86cde9..713c2f6 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs +++ b/DTOs/SpecificationAttributes/SpecificationAttributeOptionDto.cs @@ -1,11 +1,9 @@ -using FluentValidation.Attributes; -using Newtonsoft.Json; -using Nop.Plugin.Api.Validators; +using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { [JsonObject(Title = "specification_attribute_option")] - [Validator(typeof(SpecificationAttributeOptionDtoValidator))] + //[Validator(typeof(SpecificationAttributeOptionDtoValidator))] public class SpecificationAttributeOptionDto { /// diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs b/DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs similarity index 75% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs rename to DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs index 4961ee3..e425843 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs +++ b/DTOs/SpecificationAttributes/SpecificationAttributesCountRootObject.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { public class SpecificationAttributesCountRootObject { diff --git a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs b/DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs similarity index 92% rename from Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs rename to DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs index 654a00a..5b39645 100644 --- a/Nop.Plugin.Api/DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs +++ b/DTOs/SpecificationAttributes/SpecificationAttributesRootObjectDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.SpecificationAttributes +namespace Nop.Plugin.Api.DTO.SpecificationAttributes { public class SpecificationAttributesRootObjectDto : ISerializableObject { diff --git a/Nop.Plugin.Api/DTOs/Stores/StoreDto.cs b/DTOs/Stores/StoreDto.cs similarity index 97% rename from Nop.Plugin.Api/DTOs/Stores/StoreDto.cs rename to DTOs/Stores/StoreDto.cs index a1a7a1a..8b27cbf 100644 --- a/Nop.Plugin.Api/DTOs/Stores/StoreDto.cs +++ b/DTOs/Stores/StoreDto.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; -namespace Nop.Plugin.Api.DTOs.Stores +namespace Nop.Plugin.Api.DTO.Stores { [JsonObject(Title = "store")] public class StoreDto : BaseDto diff --git a/Nop.Plugin.Api/DTOs/Stores/StoresRootObject.cs b/DTOs/Stores/StoresRootObject.cs similarity index 93% rename from Nop.Plugin.Api/DTOs/Stores/StoresRootObject.cs rename to DTOs/Stores/StoresRootObject.cs index 2ec14b1..e030f54 100644 --- a/Nop.Plugin.Api/DTOs/Stores/StoresRootObject.cs +++ b/DTOs/Stores/StoresRootObject.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Nop.Plugin.Api.DTOs.Stores +namespace Nop.Plugin.Api.DTO.Stores { public class StoresRootObject : ISerializableObject { diff --git a/DTOs/TaxCategory/TaxCategoryDto.cs b/DTOs/TaxCategory/TaxCategoryDto.cs new file mode 100644 index 0000000..bf77b91 --- /dev/null +++ b/DTOs/TaxCategory/TaxCategoryDto.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json; +using Nop.Plugin.Api.DTO.Base; +using Nop.Plugin.Api.Validators; + +namespace Nop.Plugin.Api.DTO.TaxCategory +{ + [JsonObject(Title = "taxcategory")] + //[Validator(typeof(TaxCategoryDtoValidator))] + public class TaxCategoryDto : BaseDto + { + /// + /// Gets or sets the name + /// + public string Name { get; set; } + + /// + /// Gets or sets the display order + /// + public int DisplayOrder { get; set; } + + /// + /// Gets or sets the tax rate + /// + public decimal Rate { get; set; } + } +} diff --git a/DTOs/TaxCategory/TaxCategoryRootObjectDto.cs b/DTOs/TaxCategory/TaxCategoryRootObjectDto.cs new file mode 100644 index 0000000..8e26279 --- /dev/null +++ b/DTOs/TaxCategory/TaxCategoryRootObjectDto.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Nop.Plugin.Api.DTO.TaxCategory +{ + public class TaxCategoryRootObjectDto : ISerializableObject + { + public TaxCategoryRootObjectDto() + { + TaxCategories = new List(); + } + + [JsonProperty("tax_categories")] + public IList TaxCategories { get; set; } + + public string GetPrimaryPropertyName() + { + return "tax_categories"; + } + + public Type GetPrimaryPropertyType() + { + return typeof(TaxCategoryDto); + } + } +} diff --git a/Nop.Plugin.Api/DataStructures/ApiList.cs b/DataStructures/ApiList.cs similarity index 100% rename from Nop.Plugin.Api/DataStructures/ApiList.cs rename to DataStructures/ApiList.cs diff --git a/Nop.Plugin.Api/Delta/Delta.cs b/Delta/Delta.cs similarity index 96% rename from Nop.Plugin.Api/Delta/Delta.cs rename to Delta/Delta.cs index be6a313..6a3b76a 100644 --- a/Nop.Plugin.Api/Delta/Delta.cs +++ b/Delta/Delta.cs @@ -1,148 +1,148 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.Maps; - -namespace Nop.Plugin.Api.Delta -{ - public class Delta where TDto : class, new() - { - private TDto _dto; - - private readonly IMappingHelper _mappingHelper = new MappingHelper(); - - private readonly Dictionary _changedJsonPropertyNames; - - private readonly IJsonPropertyMapper _jsonPropertyMapper; - - public Dictionary ObjectPropertyNameValuePairs = new Dictionary(); - - private Dictionary _propertyValuePairs; - - private Dictionary PropertyValuePairs - { - get - { - if (_propertyValuePairs == null) - { - _propertyValuePairs = GetPropertyValuePairs(typeof(TDto), _changedJsonPropertyNames); - } - - return _propertyValuePairs; - } - } - - public TDto Dto - { - get - { - if (_dto == null) - { - _dto = new TDto(); - } - - return _dto; - } - } - - public Delta(Dictionary passedChangedJsonPropertyValuePaires) - { - _jsonPropertyMapper = EngineContext.Current.Resolve(); - _changedJsonPropertyNames = passedChangedJsonPropertyValuePaires; - - _mappingHelper.SetValues(PropertyValuePairs, Dto, typeof(TDto), ObjectPropertyNameValuePairs, true); - } - - public void Merge(TEntity entity, bool mergeComplexTypeCollections = true) - { - _mappingHelper.SetValues(PropertyValuePairs, entity, entity.GetType(), null,mergeComplexTypeCollections); - } - - public void Merge(object dto, TEntity entity, bool mergeComplexTypeCollections = true) - { - if (dto != null && ObjectPropertyNameValuePairs.ContainsKey(dto)) - { - var propertyValuePairs = ObjectPropertyNameValuePairs[dto] as Dictionary; - _mappingHelper.SetValues(propertyValuePairs, entity, entity.GetType(), null, mergeComplexTypeCollections); - } - } - - private Dictionary GetPropertyValuePairs(Type type, Dictionary changedJsonPropertyNames) - { - var propertyValuePairs = new Dictionary(); - - if (changedJsonPropertyNames == null) - return propertyValuePairs; - - var typeMap = _jsonPropertyMapper.GetMap(type); - - foreach (var changedProperty in changedJsonPropertyNames) - { - var jsonName = changedProperty.Key; - - if (typeMap.ContainsKey(jsonName)) - { - var propertyNameAndType = typeMap[jsonName]; - - var propertyName = propertyNameAndType.Item1; - var propertyType = propertyNameAndType.Item2; - - // Handle system types - // This is also the recursion base - if (propertyType.Namespace == "System") - { - propertyValuePairs.Add(propertyName, changedProperty.Value); - } - // Handle collections - else if (propertyType.GetInterface(typeof(IEnumerable).FullName) != null) - { - // skip any collections that are passed as null - // we can handle only empty collection, which will delete any items if exist - // or collections that has some elements which need to be updated/added/deleted. - if(changedProperty.Value == null) - continue; - - var collection = changedProperty.Value as IEnumerable; - var collectionElementsType = propertyType.GetGenericArguments()[0]; - var resultCollection = new List(); - - foreach (var item in collection) - { - // Simple types in collection - if (collectionElementsType.Namespace == "System") - { - resultCollection.Add(item); - } - // Complex types in collection - else - { - // the complex type could be null so we try a defensive cast - var itemDictionary = - item as Dictionary; - - resultCollection.Add(GetPropertyValuePairs(collectionElementsType,itemDictionary)); - } - } - - propertyValuePairs.Add(propertyName, resultCollection); - } - // Handle nested properties - else - { - // the complex type could be null so we try a defensive cast - var changedPropertyValueDictionary = - changedProperty.Value as Dictionary; - - var resultedNestedObject = GetPropertyValuePairs(propertyType, changedPropertyValueDictionary); - - propertyValuePairs.Add(propertyName, resultedNestedObject); - } - } - } - - return propertyValuePairs; - } - } +using System; +using System.Collections; +using System.Collections.Generic; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.Maps; + +namespace Nop.Plugin.Api.Delta +{ + public class Delta where TDto : class, new() + { + private TDto _dto; + + private readonly IMappingHelper _mappingHelper = new MappingHelper(); + + private readonly Dictionary _changedJsonPropertyNames; + + private readonly IJsonPropertyMapper _jsonPropertyMapper; + + public Dictionary ObjectPropertyNameValuePairs = new Dictionary(); + + private Dictionary _propertyValuePairs; + + private Dictionary PropertyValuePairs + { + get + { + if (_propertyValuePairs == null) + { + _propertyValuePairs = GetPropertyValuePairs(typeof(TDto), _changedJsonPropertyNames); + } + + return _propertyValuePairs; + } + } + + public TDto Dto + { + get + { + if (_dto == null) + { + _dto = new TDto(); + } + + return _dto; + } + } + + public Delta(Dictionary passedChangedJsonPropertyValuePaires) + { + _jsonPropertyMapper = EngineContext.Current.Resolve(); + _changedJsonPropertyNames = passedChangedJsonPropertyValuePaires; + + _mappingHelper.SetValues(PropertyValuePairs, Dto, typeof(TDto), ObjectPropertyNameValuePairs, true); + } + + public void Merge(TEntity entity, bool mergeComplexTypeCollections = true) + { + _mappingHelper.SetValues(PropertyValuePairs, entity, entity.GetType(), null, mergeComplexTypeCollections); + } + + public void Merge(object dto, TEntity entity, bool mergeComplexTypeCollections = true) + { + if (dto != null && ObjectPropertyNameValuePairs.ContainsKey(dto)) + { + var propertyValuePairs = ObjectPropertyNameValuePairs[dto] as Dictionary; + _mappingHelper.SetValues(propertyValuePairs, entity, entity.GetType(), null, mergeComplexTypeCollections); + } + } + + private Dictionary GetPropertyValuePairs(Type type, Dictionary changedJsonPropertyNames) + { + var propertyValuePairs = new Dictionary(); + + if (changedJsonPropertyNames == null) + return propertyValuePairs; + + var typeMap = _jsonPropertyMapper.GetMap(type); + + foreach (var changedProperty in changedJsonPropertyNames) + { + var jsonName = changedProperty.Key; + + if (typeMap.ContainsKey(jsonName)) + { + var propertyNameAndType = typeMap[jsonName]; + + var propertyName = propertyNameAndType.Item1; + var propertyType = propertyNameAndType.Item2; + + // Handle system types + // This is also the recursion base + if (propertyType.Namespace == "System") + { + propertyValuePairs.Add(propertyName, changedProperty.Value); + } + // Handle collections + else if (propertyType.GetInterface(typeof(IEnumerable).FullName) != null) + { + // skip any collections that are passed as null + // we can handle only empty collection, which will delete any items if exist + // or collections that has some elements which need to be updated/added/deleted. + if(changedProperty.Value == null) + continue; + + var collection = changedProperty.Value as IEnumerable; + var collectionElementsType = propertyType.GetGenericArguments()[0]; + var resultCollection = new List(); + + foreach (var item in collection) + { + // Simple types in collection + if (collectionElementsType.Namespace == "System") + { + resultCollection.Add(item); + } + // Complex types in collection + else + { + // the complex type could be null so we try a defensive cast + var itemDictionary = + item as Dictionary; + + resultCollection.Add(GetPropertyValuePairs(collectionElementsType,itemDictionary)); + } + } + + propertyValuePairs.Add(propertyName, resultCollection); + } + // Handle nested properties + else + { + // the complex type could be null so we try a defensive cast + var changedPropertyValueDictionary = + changedProperty.Value as Dictionary; + + var resultedNestedObject = GetPropertyValuePairs(propertyType, changedPropertyValueDictionary); + + propertyValuePairs.Add(propertyName, resultedNestedObject); + } + } + } + + return propertyValuePairs; + } + } } \ No newline at end of file diff --git a/Domain/ApiSettings.cs b/Domain/ApiSettings.cs new file mode 100644 index 0000000..1161ad8 --- /dev/null +++ b/Domain/ApiSettings.cs @@ -0,0 +1,11 @@ +using Nop.Core.Configuration; + +namespace Nop.Plugin.Api.Domain +{ + public class ApiSettings : ISettings + { + public bool EnableApi { get; set; } = true; + + public int TokenExpiryInDays { get; set; } = 0; + } +} diff --git a/Nop.Plugin.Api/Domain/WebHooks.cs b/Domain/WebHooks.cs similarity index 100% rename from Nop.Plugin.Api/Domain/WebHooks.cs rename to Domain/WebHooks.cs diff --git a/Nop.Plugin.Api/Factories/AddressFactory.cs b/Factories/AddressFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/AddressFactory.cs rename to Factories/AddressFactory.cs diff --git a/Nop.Plugin.Api/Factories/CategoryFactory.cs b/Factories/CategoryFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/CategoryFactory.cs rename to Factories/CategoryFactory.cs diff --git a/Nop.Plugin.Api/Factories/CustomerFactory.cs b/Factories/CustomerFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/CustomerFactory.cs rename to Factories/CustomerFactory.cs diff --git a/Nop.Plugin.Api/Factories/IFactory.cs b/Factories/IFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/IFactory.cs rename to Factories/IFactory.cs diff --git a/Nop.Plugin.Api/Factories/ManufacturerFactory.cs b/Factories/ManufacturerFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/ManufacturerFactory.cs rename to Factories/ManufacturerFactory.cs diff --git a/Nop.Plugin.Api/Factories/OrderFactory.cs b/Factories/OrderFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/OrderFactory.cs rename to Factories/OrderFactory.cs diff --git a/Nop.Plugin.Api/Factories/ProductFactory.cs b/Factories/ProductFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/ProductFactory.cs rename to Factories/ProductFactory.cs diff --git a/Nop.Plugin.Api/Factories/ShoppingCartItemFactory.cs b/Factories/ShoppingCartItemFactory.cs similarity index 100% rename from Nop.Plugin.Api/Factories/ShoppingCartItemFactory.cs rename to Factories/ShoppingCartItemFactory.cs diff --git a/Nop.Plugin.Api/Helpers/CryptoHelper.cs b/Helpers/CryptoHelper.cs similarity index 97% rename from Nop.Plugin.Api/Helpers/CryptoHelper.cs rename to Helpers/CryptoHelper.cs index 4a00119..c35de17 100644 --- a/Nop.Plugin.Api/Helpers/CryptoHelper.cs +++ b/Helpers/CryptoHelper.cs @@ -1,106 +1,106 @@ -using Nop.Core.Infrastructure; - -namespace Nop.Plugin.Api.Helpers -{ - using Microsoft.IdentityModel.Tokens; - using Newtonsoft.Json; - using System.IO; - using System.Security.Cryptography; - using Nop.Core; - using Microsoft.Extensions.DependencyInjection; - - - public static class CryptoHelper - { - // Need to ensure that the key would be the same through the application lifetime. - private static RsaSecurityKey _key; - private const string TokenSigningKeyFileName = "api-token-signing-key.json"; - - public static RsaSecurityKey CreateRsaSecurityKey() - { - if (_key == null) - { - string pathToKey = CommonHelper.DefaultFileProvider.MapPath($"~/App_Data/{TokenSigningKeyFileName}"); - - if (!File.Exists(pathToKey)) - { - // generate random parameters - var randomParameters = GetRandomParameters(); - - var rsaParams = new RSAParametersWithPrivate(); - rsaParams.SetParameters(randomParameters); - string serializedParameters = JsonConvert.SerializeObject(rsaParams); - - // create file and save the key - File.WriteAllText(pathToKey, serializedParameters); - } - - // load the key - if (!File.Exists(pathToKey)) - throw new FileNotFoundException("Check configuration - cannot find auth key file: " + pathToKey); - - var keyParams = JsonConvert.DeserializeObject(File.ReadAllText(pathToKey)); - - // create signing key by the key above - _key = new RsaSecurityKey(keyParams.ToRSAParameters()); - } - - return _key; - } - - public static RSAParameters GetRandomParameters() - { - using (var rsa = new RSACryptoServiceProvider(2048)) - { - try - { - return rsa.ExportParameters(true); - } - finally - { - rsa.PersistKeyInCsp = false; - } - } - } - - // https://github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample/blob/master/src/TokenAuthExampleWebApplication/RSAKeyUtils.cs - private class RSAParametersWithPrivate - { - public byte[] D { get; set; } - public byte[] DP { get; set; } - public byte[] DQ { get; set; } - public byte[] Exponent { get; set; } - public byte[] InverseQ { get; set; } - public byte[] Modulus { get; set; } - public byte[] P { get; set; } - public byte[] Q { get; set; } - - public void SetParameters(RSAParameters p) - { - D = p.D; - DP = p.DP; - DQ = p.DQ; - Exponent = p.Exponent; - InverseQ = p.InverseQ; - Modulus = p.Modulus; - P = p.P; - Q = p.Q; - } - public RSAParameters ToRSAParameters() - { - return new RSAParameters() - { - D = this.D, - DP = this.DP, - DQ = this.DQ, - Exponent = this.Exponent, - InverseQ = this.InverseQ, - Modulus = this.Modulus, - P = this.P, - Q = this.Q - - }; - } - } - } +using Nop.Core.Infrastructure; + +namespace Nop.Plugin.Api.Helpers +{ + using Microsoft.IdentityModel.Tokens; + using Newtonsoft.Json; + using System.IO; + using System.Security.Cryptography; + using Nop.Core; + using Microsoft.Extensions.DependencyInjection; + + + public static class CryptoHelper + { + // Need to ensure that the key would be the same through the application lifetime. + private static RsaSecurityKey _key; + private const string TokenSigningKeyFileName = "api-token-signing-key.json"; + + public static RsaSecurityKey CreateRsaSecurityKey() + { + if (_key == null) + { + string pathToKey = CommonHelper.DefaultFileProvider.MapPath($"~/App_Data/{TokenSigningKeyFileName}"); + + if (!File.Exists(pathToKey)) + { + // generate random parameters + var randomParameters = GetRandomParameters(); + + var rsaParams = new RSAParametersWithPrivate(); + rsaParams.SetParameters(randomParameters); + string serializedParameters = JsonConvert.SerializeObject(rsaParams); + + // create file and save the key + File.WriteAllText(pathToKey, serializedParameters); + } + + // load the key + if (!File.Exists(pathToKey)) + throw new FileNotFoundException("Check configuration - cannot find auth key file: " + pathToKey); + + var keyParams = JsonConvert.DeserializeObject(File.ReadAllText(pathToKey)); + + // create signing key by the key above + _key = new RsaSecurityKey(keyParams.ToRSAParameters()); + } + + return _key; + } + + public static RSAParameters GetRandomParameters() + { + using (var rsa = new RSACryptoServiceProvider(2048)) + { + try + { + return rsa.ExportParameters(true); + } + finally + { + rsa.PersistKeyInCsp = false; + } + } + } + + // https://github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample/blob/master/src/TokenAuthExampleWebApplication/RSAKeyUtils.cs + private class RSAParametersWithPrivate + { + public byte[] D { get; set; } + public byte[] DP { get; set; } + public byte[] DQ { get; set; } + public byte[] Exponent { get; set; } + public byte[] InverseQ { get; set; } + public byte[] Modulus { get; set; } + public byte[] P { get; set; } + public byte[] Q { get; set; } + + public void SetParameters(RSAParameters p) + { + D = p.D; + DP = p.DP; + DQ = p.DQ; + Exponent = p.Exponent; + InverseQ = p.InverseQ; + Modulus = p.Modulus; + P = p.P; + Q = p.Q; + } + public RSAParameters ToRSAParameters() + { + return new RSAParameters() + { + D = this.D, + DP = this.DP, + DQ = this.DQ, + Exponent = this.Exponent, + InverseQ = this.InverseQ, + Modulus = this.Modulus, + P = this.P, + Q = this.Q + + }; + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Helpers/CustomerRolesHelper.cs b/Helpers/CustomerRolesHelper.cs similarity index 83% rename from Nop.Plugin.Api/Helpers/CustomerRolesHelper.cs rename to Helpers/CustomerRolesHelper.cs index 4aa7cd1..064ec8e 100644 --- a/Nop.Plugin.Api/Helpers/CustomerRolesHelper.cs +++ b/Helpers/CustomerRolesHelper.cs @@ -1,51 +1,52 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Caching; -using Nop.Core.Domain.Customers; -using Nop.Services.Customers; - -namespace Nop.Plugin.Api.Helpers -{ - public class CustomerRolesHelper : ICustomerRolesHelper - { - private const string CUSTOMERROLES_ALL_KEY = "Nop.customerrole.all-{0}"; - - private readonly ICustomerService _customerService; - private readonly ICacheManager _cacheManager; - - public CustomerRolesHelper(ICustomerService customerService, ICacheManager cacheManager) - { - _customerService = customerService; - _cacheManager = cacheManager; - } - - public IList GetValidCustomerRoles(List roleIds) - { - // This is needed because the caching messeup the entity framework context - // and when you try to send something TO the database it throws an exeption. - _cacheManager.RemoveByPattern(CUSTOMERROLES_ALL_KEY); - - var allCustomerRoles = _customerService.GetAllCustomerRoles(true); - var newCustomerRoles = new List(); - foreach (var customerRole in allCustomerRoles) - { - if (roleIds != null && roleIds.Contains(customerRole.Id)) - { - newCustomerRoles.Add(customerRole); - } - } - - return newCustomerRoles; - } - - public bool IsInGuestsRole(IList customerRoles) - { - return customerRoles.FirstOrDefault(cr => cr.SystemName == NopCustomerDefaults.GuestsRoleName) != null; - } - - public bool IsInRegisteredRole(IList customerRoles) - { - return customerRoles.FirstOrDefault(cr => cr.SystemName == NopCustomerDefaults.RegisteredRoleName) != null; - } - } -} \ No newline at end of file +using System.Collections.Generic; +using System.Linq; +using Nop.Core.Caching; +using Nop.Core.Domain.Customers; +using Nop.Services.Customers; + +namespace Nop.Plugin.Api.Helpers +{ + public class CustomerRolesHelper : ICustomerRolesHelper + { + private const string CUSTOMERROLES_ALL_KEY = "Nop.customerrole.all-{0}"; + private readonly IStaticCacheManager _cacheManager; + + private readonly ICustomerService _customerService; + + public CustomerRolesHelper(ICustomerService customerService, IStaticCacheManager cacheManager) + { + _customerService = customerService; + _cacheManager = cacheManager; + } + + public IList GetValidCustomerRoles(List roleIds) + { + // This is needed because the caching messes up the entity framework context + // and when you try to send something TO the database it throws an exception. + _cacheManager.RemoveByPrefix(CUSTOMERROLES_ALL_KEY); + + var allCustomerRoles = _customerService.GetAllCustomerRoles(true); + var newCustomerRoles = new List(); + foreach (var customerRole in allCustomerRoles) + { + if (roleIds != null && roleIds.Contains(customerRole.Id)) + { + newCustomerRoles.Add(customerRole); + } + } + + return newCustomerRoles; + } + + public bool IsInGuestsRole(IList customerRoles) + { + return customerRoles.FirstOrDefault(cr => cr.SystemName == NopCustomerDefaults.GuestsRoleName) != null; + } + + public bool IsInRegisteredRole(IList customerRoles) + { + return customerRoles.FirstOrDefault(cr => cr.SystemName == NopCustomerDefaults.RegisteredRoleName) != null; + } + + } +} diff --git a/Nop.Plugin.Api/Helpers/DTOHelper.cs b/Helpers/DTOHelper.cs similarity index 61% rename from Nop.Plugin.Api/Helpers/DTOHelper.cs rename to Helpers/DTOHelper.cs index 395ab62..783b969 100644 --- a/Nop.Plugin.Api/Helpers/DTOHelper.cs +++ b/Helpers/DTOHelper.cs @@ -1,433 +1,555 @@ -using Nop.Core; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Directory; -using Nop.Core.Domain.Localization; -using Nop.Core.Domain.Media; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Stores; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.DTOs.Images; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.DTOs.Manufacturers; -using Nop.Plugin.Api.DTOs.ProductAttributes; -using Nop.Plugin.Api.DTOs.Products; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; -using Nop.Plugin.Api.DTOs.Stores; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.Services; -using Nop.Services.Catalog; -using Nop.Services.Directory; -using Nop.Services.Localization; -using Nop.Services.Media; -using Nop.Services.Security; -using Nop.Services.Seo; -using Nop.Services.Stores; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Nop.Plugin.Api.Helpers -{ - public class DTOHelper : IDTOHelper - { - private readonly IAclService _aclService; - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; - private readonly ICustomerApiService _customerApiService; - private readonly ILanguageService _languageService; - private readonly ILocalizationService _localizationService; - private readonly IPictureService _pictureService; - private readonly IProductAttributeConverter _productAttributeConverter; - private readonly IProductAttributeService _productAttributeService; - private readonly IProductService _productService; - private readonly IProductTagService _productTagService; - private readonly IStoreMappingService _storeMappingService; - private readonly IStoreService _storeService; - private readonly IUrlRecordService _urlRecordService; - - public DTOHelper(IProductService productService, - IAclService aclService, - IStoreMappingService storeMappingService, - IPictureService pictureService, - IProductAttributeService productAttributeService, - ICustomerApiService customerApiService, - IProductAttributeConverter productAttributeConverter, - ILanguageService languageService, - ICurrencyService currencyService, - CurrencySettings currencySettings, - IStoreService storeService, - ILocalizationService localizationService, - IUrlRecordService urlRecordService, - IProductTagService productTagService) - { - _productService = productService; - _aclService = aclService; - _storeMappingService = storeMappingService; - _pictureService = pictureService; - _productAttributeService = productAttributeService; - _customerApiService = customerApiService; - _productAttributeConverter = productAttributeConverter; - _languageService = languageService; - _currencyService = currencyService; - _currencySettings = currencySettings; - _storeService = storeService; - _localizationService = localizationService; - _urlRecordService = urlRecordService; - _productTagService = productTagService; - } - - public ProductDto PrepareProductDTO(Product product) - { - var productDto = product.ToDto(); - - PrepareProductImages(product.ProductPictures, productDto); - - productDto.SeName = _urlRecordService.GetSeName(product); - productDto.DiscountIds = product.AppliedDiscounts.Select(discount => discount.Id).ToList(); - productDto.ManufacturerIds = product.ProductManufacturers.Select(pm => pm.ManufacturerId).ToList(); - productDto.RoleIds = _aclService.GetAclRecords(product).Select(acl => acl.CustomerRoleId).ToList(); - productDto.StoreIds = _storeMappingService.GetStoreMappings(product).Select(mapping => mapping.StoreId) - .ToList(); - productDto.Tags = _productTagService.GetAllProductTagsByProductId(product.Id).Select(tag => tag.Name) - .ToList(); - - productDto.AssociatedProductIds = - _productService.GetAssociatedProducts(product.Id, showHidden: true) - .Select(associatedProduct => associatedProduct.Id) - .ToList(); - - var allLanguages = _languageService.GetAllLanguages(); - - productDto.LocalizedNames = new List(); - - foreach (var language in allLanguages) - { - var localizedNameDto = new LocalizedNameDto - { - LanguageId = language.Id, - LocalizedName = _localizationService.GetLocalized(product, x => x.Name, language.Id) - }; - - productDto.LocalizedNames.Add(localizedNameDto); - } - - return productDto; - } - - public CategoryDto PrepareCategoryDTO(Category category) - { - var categoryDto = category.ToDto(); - - var picture = _pictureService.GetPictureById(category.PictureId); - var imageDto = PrepareImageDto(picture); - - if (imageDto != null) - { - categoryDto.Image = imageDto; - } - - categoryDto.SeName = _urlRecordService.GetSeName(category); - categoryDto.DiscountIds = category.AppliedDiscounts.Select(discount => discount.Id).ToList(); - categoryDto.RoleIds = _aclService.GetAclRecords(category).Select(acl => acl.CustomerRoleId).ToList(); - categoryDto.StoreIds = _storeMappingService.GetStoreMappings(category).Select(mapping => mapping.StoreId) - .ToList(); - - var allLanguages = _languageService.GetAllLanguages(); - - categoryDto.LocalizedNames = new List(); - - foreach (var language in allLanguages) - { - var localizedNameDto = new LocalizedNameDto - { - LanguageId = language.Id, - LocalizedName = _localizationService.GetLocalized(category, x => x.Name, language.Id) - }; - - categoryDto.LocalizedNames.Add(localizedNameDto); - } - - return categoryDto; - } - - public OrderDto PrepareOrderDTO(Order order) - { - var orderDto = order.ToDto(); - - orderDto.OrderItems = order.OrderItems.Select(PrepareOrderItemDTO).ToList(); - - var customerDto = _customerApiService.GetCustomerById(order.Customer.Id); - - if (customerDto != null) - { - orderDto.Customer = customerDto.ToOrderCustomerDto(); - } - - return orderDto; - } - - public ShoppingCartItemDto PrepareShoppingCartItemDTO(ShoppingCartItem shoppingCartItem) - { - var dto = shoppingCartItem.ToDto(); - dto.ProductDto = PrepareProductDTO(shoppingCartItem.Product); - dto.CustomerDto = shoppingCartItem.Customer.ToCustomerForShoppingCartItemDto(); - dto.Attributes = _productAttributeConverter.Parse(shoppingCartItem.AttributesXml); - return dto; - } - - public OrderItemDto PrepareOrderItemDTO(OrderItem orderItem) - { - var dto = orderItem.ToDto(); - dto.Product = PrepareProductDTO(orderItem.Product); - dto.Attributes = _productAttributeConverter.Parse(orderItem.AttributesXml); - return dto; - } - - public StoreDto PrepareStoreDTO(Store store) - { - var storeDto = store.ToDto(); - - var primaryCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); - - if (!string.IsNullOrEmpty(primaryCurrency.DisplayLocale)) - { - storeDto.PrimaryCurrencyDisplayLocale = primaryCurrency.DisplayLocale; - } - - storeDto.LanguageIds = _languageService.GetAllLanguages(false, store.Id).Select(x => x.Id).ToList(); - - return storeDto; - } - - public LanguageDto PrepateLanguageDto(Language language) - { - var languageDto = language.ToDto(); - - languageDto.StoreIds = _storeMappingService.GetStoreMappings(language).Select(mapping => mapping.StoreId) - .ToList(); - - if (languageDto.StoreIds.Count == 0) - { - languageDto.StoreIds = _storeService.GetAllStores().Select(s => s.Id).ToList(); - } - - return languageDto; - } - - public ProductAttributeDto PrepareProductAttributeDTO(ProductAttribute productAttribute) - { - return productAttribute.ToDto(); - } - - private void PrepareProductImages(IEnumerable productPictures, ProductDto productDto) - { - if (productDto.Images == null) - { - productDto.Images = new List(); - } - - // Here we prepare the resulted dto image. - foreach (var productPicture in productPictures) - { - var imageDto = PrepareImageDto(productPicture.Picture); - - if (imageDto != null) - { - var productImageDto = new ImageMappingDto - { - Id = productPicture.Id, - PictureId = productPicture.PictureId, - Position = productPicture.DisplayOrder, - Src = imageDto.Src, - Attachment = imageDto.Attachment - }; - - productDto.Images.Add(productImageDto); - } - } - } - - protected ImageDto PrepareImageDto(Picture picture) - { - ImageDto image = null; - - if (picture != null) - { - // We don't use the image from the passed dto directly - // because the picture may be passed with src and the result should only include the base64 format. - image = new ImageDto - { - //Attachment = Convert.ToBase64String(picture.PictureBinary), - Src = _pictureService.GetPictureUrl(picture) - }; - } - - return image; - } - - private void PrepareProductAttributes(IEnumerable productAttributeMappings, - ProductDto productDto) - { - if (productDto.ProductAttributeMappings == null) - { - productDto.ProductAttributeMappings = new List(); - } - - foreach (var productAttributeMapping in productAttributeMappings) - { - var productAttributeMappingDto = - PrepareProductAttributeMappingDto(productAttributeMapping); - - if (productAttributeMappingDto != null) - { - productDto.ProductAttributeMappings.Add(productAttributeMappingDto); - } - } - } - - private ProductAttributeMappingDto PrepareProductAttributeMappingDto( - ProductAttributeMapping productAttributeMapping) - { - ProductAttributeMappingDto productAttributeMappingDto = null; - - if (productAttributeMapping != null) - { - productAttributeMappingDto = new ProductAttributeMappingDto - { - Id = productAttributeMapping.Id, - ProductAttributeId = productAttributeMapping.ProductAttributeId, - ProductAttributeName = _productAttributeService - .GetProductAttributeById(productAttributeMapping.ProductAttributeId).Name, - TextPrompt = productAttributeMapping.TextPrompt, - DefaultValue = productAttributeMapping.DefaultValue, - AttributeControlTypeId = productAttributeMapping.AttributeControlTypeId, - DisplayOrder = productAttributeMapping.DisplayOrder, - IsRequired = productAttributeMapping.IsRequired, - ProductAttributeValues = productAttributeMapping.ProductAttributeValues - .Select(x => PrepareProductAttributeValueDto(x, productAttributeMapping.Product)).ToList() - }; - } - - return productAttributeMappingDto; - } - - private ProductAttributeValueDto PrepareProductAttributeValueDto(ProductAttributeValue productAttributeValue, - Product product) - { - ProductAttributeValueDto productAttributeValueDto = null; - - if (productAttributeValue != null) - { - productAttributeValueDto = productAttributeValue.ToDto(); - if (productAttributeValue.ImageSquaresPictureId > 0) - { - var imageSquaresPicture = - _pictureService.GetPictureById(productAttributeValue.ImageSquaresPictureId); - var imageDto = PrepareImageDto(imageSquaresPicture); - productAttributeValueDto.ImageSquaresImage = imageDto; - } - - if (productAttributeValue.PictureId > 0) - { - // make sure that the picture is mapped to the product - // This is needed since if you delete the product picture mapping from the nopCommerce administrationthe - // then the attribute value is not updated and it will point to a picture that has been deleted - var productPicture = - product.ProductPictures.FirstOrDefault(pp => pp.PictureId == productAttributeValue.PictureId); - if (productPicture != null) - { - productAttributeValueDto.ProductPictureId = productPicture.Id; - } - } - } - - return productAttributeValueDto; - } - - private void PrepareProductAttributeCombinations(IEnumerable productAttributeCombinations, - ProductDto productDto) - { - productDto.ProductAttributeCombinations = productDto.ProductAttributeCombinations ?? new List(); - - foreach (var productAttributeCombination in productAttributeCombinations) - { - var productAttributeCombinationDto = PrepareProductAttributeCombinationDto(productAttributeCombination); - if (productAttributeCombinationDto != null) - { - productDto.ProductAttributeCombinations.Add(productAttributeCombinationDto); - } - } - } - - private ProductAttributeCombinationDto PrepareProductAttributeCombinationDto(ProductAttributeCombination productAttributeCombination) - { - return productAttributeCombination.ToDto(); - } - - public void PrepareProductSpecificationAttributes(IEnumerable productSpecificationAttributes, ProductDto productDto) - { - if (productDto.ProductSpecificationAttributes == null) - productDto.ProductSpecificationAttributes = new List(); - - foreach (var productSpecificationAttribute in productSpecificationAttributes) - { - ProductSpecificationAttributeDto productSpecificationAttributeDto = PrepareProductSpecificationAttributeDto(productSpecificationAttribute); - - if (productSpecificationAttributeDto != null) - { - productDto.ProductSpecificationAttributes.Add(productSpecificationAttributeDto); - } - } - } - - public ProductSpecificationAttributeDto PrepareProductSpecificationAttributeDto(ProductSpecificationAttribute productSpecificationAttribute) - { - return productSpecificationAttribute.ToDto(); - } - - public SpecificationAttributeDto PrepareSpecificationAttributeDto(SpecificationAttribute specificationAttribute) - { - return specificationAttribute.ToDto(); - } - - public ManufacturerDto PrepareManufacturerDto(Manufacturer manufacturer) - { - var manufacturerDto = manufacturer.ToDto(); - - var picture = _pictureService.GetPictureById(manufacturer.PictureId); - var imageDto = PrepareImageDto(picture); - - if (imageDto != null) - { - manufacturerDto.Image = imageDto; - } - - manufacturerDto.SeName = _urlRecordService.GetSeName(manufacturer); - manufacturerDto.DiscountIds = manufacturer.AppliedDiscounts.Select(discount => discount.Id).ToList(); - manufacturerDto.RoleIds = _aclService.GetAclRecords(manufacturer).Select(acl => acl.CustomerRoleId).ToList(); - manufacturerDto.StoreIds = _storeMappingService.GetStoreMappings(manufacturer).Select(mapping => mapping.StoreId) - .ToList(); - - var allLanguages = _languageService.GetAllLanguages(); - - manufacturerDto.LocalizedNames = new List(); - - foreach (var language in allLanguages) - { - var localizedNameDto = new LocalizedNameDto - { - LanguageId = language.Id, - LocalizedName = _localizationService.GetLocalized(manufacturer, x => x.Name, language.Id) - }; - - manufacturerDto.LocalizedNames.Add(localizedNameDto); - } - - return manufacturerDto; - } - } -} \ No newline at end of file +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Directory; +using Nop.Core.Domain.Localization; +using Nop.Core.Domain.Media; +using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Shipping; +using Nop.Core.Domain.Stores; +using Nop.Core.Domain.Tax; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Languages; +using Nop.Plugin.Api.DTO.Manufacturers; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.DTO.Orders; +using Nop.Plugin.Api.DTO.ProductAttributes; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.DTO.Shipments; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using Nop.Plugin.Api.DTO.SpecificationAttributes; +using Nop.Plugin.Api.DTO.Stores; +using Nop.Plugin.Api.DTO.TaxCategory; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Plugin.Api.Services; +using Nop.Services.Catalog; +using Nop.Services.Common; +using Nop.Services.Configuration; +using Nop.Services.Customers; +using Nop.Services.Directory; +using Nop.Services.Discounts; +using Nop.Services.Localization; +using Nop.Services.Media; +using Nop.Services.Orders; +using Nop.Services.Security; +using Nop.Services.Seo; +using Nop.Services.Shipping; +using Nop.Services.Stores; +using Nop.Services.Tax; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Helpers +{ + public class DTOHelper : IDTOHelper + { + private readonly CurrencySettings _currencySettings; + private readonly IAclService _aclService; + private readonly ICurrencyService _currencyService; + private readonly ICustomerApiService _customerApiService; + private readonly ICustomerService _customerService; + private readonly IDiscountService _discountService; + private readonly ILanguageService _languageService; + private readonly ILocalizationService _localizationService; + private readonly IManufacturerService _manufacturerService; + private readonly IPictureService _pictureService; + private readonly IProductAttributeConverter _productAttributeConverter; + private readonly IProductAttributeService _productAttributeService; + private readonly IProductService _productService; + private readonly IProductTagService _productTagService; + private readonly ISettingService _settingService; + private readonly IStoreMappingService _storeMappingService; + private readonly IStoreService _storeService; + private readonly ITaxCategoryService _taxCategoryService; + private readonly IUrlRecordService _urlRecordService; + private readonly IOrderService _orderService; + private readonly IShipmentService _shipmentService; + private readonly IAddressService _addressService; + + public DTOHelper(IProductService productService, + IAclService aclService, + IStoreMappingService storeMappingService, + IPictureService pictureService, + IProductAttributeService productAttributeService, + ICustomerApiService customerApiService, + ICustomerService customerService, + IProductAttributeConverter productAttributeConverter, + ILanguageService languageService, + ICurrencyService currencyService, + IDiscountService discountService, + IManufacturerService manufacturerService, + CurrencySettings currencySettings, + IStoreService storeService, + ILocalizationService localizationService, + IUrlRecordService urlRecordService, + IProductTagService productTagService, + ITaxCategoryService taxCategoryService, + ISettingService settingService, + IShipmentService shipmentService, + IOrderService orderService, + IAddressService addressService) + { + _productService = productService; + _aclService = aclService; + _storeMappingService = storeMappingService; + _pictureService = pictureService; + _productAttributeService = productAttributeService; + _customerApiService = customerApiService; + _customerService = customerService; + _productAttributeConverter = productAttributeConverter; + _languageService = languageService; + _currencyService = currencyService; + _currencySettings = currencySettings; + _storeService = storeService; + _localizationService = localizationService; + _urlRecordService = urlRecordService; + _productTagService = productTagService; + _taxCategoryService = taxCategoryService; + _settingService = settingService; + _discountService = discountService; + _manufacturerService = manufacturerService; + _orderService = orderService; + _shipmentService = shipmentService; + _addressService = addressService; + } + + public ProductDto PrepareProductDTO(Product product) + { + var productDto = product.ToDto(); + + var productPictures = _productService.GetProductPicturesByProductId(product.Id); + PrepareProductImages(productPictures, productDto); + + + productDto.SeName = _urlRecordService.GetSeName(product); + productDto.DiscountIds = _discountService.GetAppliedDiscounts(product).Select(discount => discount.Id).ToList(); + productDto.ManufacturerIds = _manufacturerService.GetProductManufacturersByProductId(product.Id).Select(pm => pm.Id).ToList(); + productDto.RoleIds = _aclService.GetAclRecords(product).Select(acl => acl.CustomerRoleId).ToList(); + productDto.StoreIds = _storeMappingService.GetStoreMappings(product).Select(mapping => mapping.StoreId) + .ToList(); + productDto.Tags = _productTagService.GetAllProductTagsByProductId(product.Id).Select(tag => tag.Name) + .ToList(); + + productDto.AssociatedProductIds = + _productService.GetAssociatedProducts(product.Id, showHidden: true) + .Select(associatedProduct => associatedProduct.Id) + .ToList(); + + var allLanguages = _languageService.GetAllLanguages(); + + productDto.LocalizedNames = new List(); + + foreach (var language in allLanguages) + { + var localizedNameDto = new LocalizedNameDto + { + LanguageId = language.Id, + LocalizedName = _localizationService.GetLocalized(product, x => x.Name, language.Id) + }; + + productDto.LocalizedNames.Add(localizedNameDto); + } + + return productDto; + } + public ImageMappingDto PrepareProductPictureDTO(ProductPicture productPicture) + { + return PrepareProductImageDto(productPicture); + } + protected ImageMappingDto PrepareProductImageDto(ProductPicture productPicture) + { + ImageMappingDto imageMapping = null; + + var picture = this._pictureService.GetPictureById(productPicture.PictureId); + + if (productPicture != null) + { + // We don't use the image from the passed dto directly + // because the picture may be passed with src and the result should only include the base64 format. + imageMapping = new ImageMappingDto + { + //Attachment = Convert.ToBase64String(picture.PictureBinary), + Id = productPicture.Id, + ProductId = productPicture.ProductId, + PictureId = productPicture.PictureId, + Position = productPicture.DisplayOrder, + MimeType = picture.MimeType, + Src = _pictureService.GetPictureUrl(productPicture.PictureId) + }; + } + + return imageMapping; + } + public CategoryDto PrepareCategoryDTO(Category category) + { + var categoryDto = category.ToDto(); + + var picture = _pictureService.GetPictureById(category.PictureId); + var imageDto = PrepareImageDto(picture); + + if (imageDto != null) + { + categoryDto.Image = imageDto; + } + + categoryDto.SeName = _urlRecordService.GetSeName(category); + categoryDto.DiscountIds = _discountService.GetAppliedDiscounts(category).Select(discount => discount.Id).ToList(); + categoryDto.RoleIds = _aclService.GetAclRecords(category).Select(acl => acl.CustomerRoleId).ToList(); + categoryDto.StoreIds = _storeMappingService.GetStoreMappings(category).Select(mapping => mapping.StoreId) + .ToList(); + + var allLanguages = _languageService.GetAllLanguages(); + + categoryDto.LocalizedNames = new List(); + + foreach (var language in allLanguages) + { + var localizedNameDto = new LocalizedNameDto + { + LanguageId = language.Id, + LocalizedName = _localizationService.GetLocalized(category, x => x.Name, language.Id) + }; + + categoryDto.LocalizedNames.Add(localizedNameDto); + } + + return categoryDto; + } + + public OrderDto PrepareOrderDTO(Order order) + { + try + { + var orderDto = order.ToDto(); + + orderDto.OrderItems = _orderService.GetOrderItems(order.Id).Select(PrepareOrderItemDTO).ToList(); + orderDto.Shipments = _shipmentService.GetShipmentsByOrderId(order.Id).Select(PrepareShippingItemDTO).ToList(); + + var billingAddress = _addressService.GetAddressById(order.BillingAddressId); + orderDto.BillingAddress = billingAddress.ToDto(); + + if (order.ShippingAddressId.HasValue) + { + var shippingAddress = _addressService.GetAddressById(order.ShippingAddressId.Value); + orderDto.ShippingAddress = shippingAddress.ToDto(); + } + + var customerDto = _customerApiService.GetCustomerById(order.CustomerId); + + if (customerDto != null) + { + orderDto.Customer = customerDto.ToOrderCustomerDto(); + } + + return orderDto; + } + catch (Exception ex) + { + throw; + } + + } + + public ShoppingCartItemDto PrepareShoppingCartItemDTO(ShoppingCartItem shoppingCartItem) + { + var dto = shoppingCartItem.ToDto(); + dto.ProductDto = PrepareProductDTO(_productService.GetProductById(shoppingCartItem.ProductId)); + dto.CustomerDto = _customerService.GetCustomerById(shoppingCartItem.CustomerId).ToCustomerForShoppingCartItemDto(); + dto.Attributes = _productAttributeConverter.Parse(shoppingCartItem.AttributesXml); + return dto; + } + + public ShipmentDto PrepareShippingItemDTO(Shipment shipment) + { + return new ShipmentDto() + { + AdminComment = shipment.AdminComment, + CreatedOnUtc = shipment.CreatedOnUtc, + DeliveryDateUtc = shipment.DeliveryDateUtc, + Id = shipment.Id, + OrderId = shipment.OrderId, + ShippedDateUtc = shipment.ShippedDateUtc, + TotalWeight = shipment.TotalWeight, + TrackingNumber = shipment.TrackingNumber + }; + + } + public OrderItemDto PrepareOrderItemDTO(OrderItem orderItem) + { + var dto = orderItem.ToDto(); + dto.Product = PrepareProductDTO(_productService.GetProductById(orderItem.ProductId)); + dto.Attributes = _productAttributeConverter.Parse(orderItem.AttributesXml); + return dto; + } + + public StoreDto PrepareStoreDTO(Store store) + { + var storeDto = store.ToDto(); + + var primaryCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + + if (!string.IsNullOrEmpty(primaryCurrency.DisplayLocale)) + { + storeDto.PrimaryCurrencyDisplayLocale = primaryCurrency.DisplayLocale; + } + + storeDto.LanguageIds = _languageService.GetAllLanguages(false, store.Id).Select(x => x.Id).ToList(); + + return storeDto; + } + + public LanguageDto PrepareLanguageDto(Language language) + { + var languageDto = language.ToDto(); + + languageDto.StoreIds = _storeMappingService.GetStoreMappings(language).Select(mapping => mapping.StoreId) + .ToList(); + + if (languageDto.StoreIds.Count == 0) + { + languageDto.StoreIds = _storeService.GetAllStores().Select(s => s.Id).ToList(); + } + + return languageDto; + } + + public ProductAttributeDto PrepareProductAttributeDTO(ProductAttribute productAttribute) + { + return productAttribute.ToDto(); + } + + private void PrepareProductImages(IEnumerable productPictures, ProductDto productDto) + { + if (productDto.Images == null) + { + productDto.Images = new List(); + } + + // Here we prepare the resulted dto image. + foreach (var productPicture in productPictures) + { + var imageDto = PrepareImageDto(_pictureService.GetPictureById(productPicture.PictureId)); + + if (imageDto != null) + { + var productImageDto = new ImageMappingDto + { + Id = productPicture.Id, + PictureId = productPicture.PictureId, + Position = productPicture.DisplayOrder, + Src = imageDto.Src, + Attachment = imageDto.Attachment + }; + + productDto.Images.Add(productImageDto); + } + } + } + + protected ImageDto PrepareImageDto(Picture picture) + { + ImageDto image = null; + + if (picture != null) + { + // We don't use the image from the passed dto directly + // because the picture may be passed with src and the result should only include the base64 format. + image = new ImageDto + { + //Attachment = Convert.ToBase64String(picture.PictureBinary), + Src = _pictureService.GetPictureUrl(picture.Id) + }; + } + + return image; + } + + + private void PrepareProductAttributes(IEnumerable productAttributeMappings, + ProductDto productDto) + { + if (productDto.ProductAttributeMappings == null) + { + productDto.ProductAttributeMappings = new List(); + } + + foreach (var productAttributeMapping in productAttributeMappings) + { + var productAttributeMappingDto = + PrepareProductAttributeMappingDto(productAttributeMapping); + + if (productAttributeMappingDto != null) + { + productDto.ProductAttributeMappings.Add(productAttributeMappingDto); + } + } + } + + private ProductAttributeMappingDto PrepareProductAttributeMappingDto( + ProductAttributeMapping productAttributeMapping) + { + ProductAttributeMappingDto productAttributeMappingDto = null; + + if (productAttributeMapping != null) + { + productAttributeMappingDto = new ProductAttributeMappingDto + { + Id = productAttributeMapping.Id, + ProductAttributeId = productAttributeMapping.ProductAttributeId, + ProductAttributeName = _productAttributeService.GetProductAttributeById(productAttributeMapping.ProductAttributeId).Name, + TextPrompt = productAttributeMapping.TextPrompt, + DefaultValue = productAttributeMapping.DefaultValue, + AttributeControlTypeId = productAttributeMapping.AttributeControlTypeId, + DisplayOrder = productAttributeMapping.DisplayOrder, + IsRequired = productAttributeMapping.IsRequired, + //TODO: Somnath + //ProductAttributeValues = _productAttributeService.GetProductAttributeValueById(productAttributeMapping.Id). + // .Select(x => + // PrepareProductAttributeValueDto(x, + // productAttributeMapping + // .Product)) + // .ToList() + }; + } + + return productAttributeMappingDto; + } + + public CustomerDto PrepareCustomerDTO(Customer customer) + { + var result = customer.ToDto(); + var customerRoles = this._customerService.GetCustomerRoles(customer); + foreach (var item in customerRoles) + { + result.RoleIds.Add(item.Id); + } + + return result; + } + + private void PrepareProductAttributeCombinations(IEnumerable productAttributeCombinations, + ProductDto productDto) + { + productDto.ProductAttributeCombinations = productDto.ProductAttributeCombinations ?? new List(); + + foreach (var productAttributeCombination in productAttributeCombinations) + { + var productAttributeCombinationDto = PrepareProductAttributeCombinationDto(productAttributeCombination); + if (productAttributeCombinationDto != null) + { + productDto.ProductAttributeCombinations.Add(productAttributeCombinationDto); + } + } + } + + private ProductAttributeCombinationDto PrepareProductAttributeCombinationDto(ProductAttributeCombination productAttributeCombination) + { + return productAttributeCombination.ToDto(); + } + + public void PrepareProductSpecificationAttributes(IEnumerable productSpecificationAttributes, ProductDto productDto) + { + if (productDto.ProductSpecificationAttributes == null) + productDto.ProductSpecificationAttributes = new List(); + + foreach (var productSpecificationAttribute in productSpecificationAttributes) + { + ProductSpecificationAttributeDto productSpecificationAttributeDto = PrepareProductSpecificationAttributeDto(productSpecificationAttribute); + + if (productSpecificationAttributeDto != null) + { + productDto.ProductSpecificationAttributes.Add(productSpecificationAttributeDto); + } + } + } + + public ProductSpecificationAttributeDto PrepareProductSpecificationAttributeDto(ProductSpecificationAttribute productSpecificationAttribute) + { + return productSpecificationAttribute.ToDto(); + } + + public SpecificationAttributeDto PrepareSpecificationAttributeDto(SpecificationAttribute specificationAttribute) + { + return specificationAttribute.ToDto(); + } + + public ManufacturerDto PrepareManufacturerDto(Manufacturer manufacturer) + { + var manufacturerDto = manufacturer.ToDto(); + + var picture = _pictureService.GetPictureById(manufacturer.PictureId); + var imageDto = PrepareImageDto(picture); + + if (imageDto != null) + { + manufacturerDto.Image = imageDto; + } + + manufacturerDto.SeName = _urlRecordService.GetSeName(manufacturer); + manufacturerDto.DiscountIds = _discountService.GetAppliedDiscounts(manufacturer).Select(discount => discount.Id).ToList(); + manufacturerDto.RoleIds = _aclService.GetAclRecords(manufacturer).Select(acl => acl.CustomerRoleId).ToList(); + manufacturerDto.StoreIds = _storeMappingService.GetStoreMappings(manufacturer).Select(mapping => mapping.StoreId) + .ToList(); + + var allLanguages = _languageService.GetAllLanguages(); + + manufacturerDto.LocalizedNames = new List(); + + foreach (var language in allLanguages) + { + var localizedNameDto = new LocalizedNameDto + { + LanguageId = language.Id, + LocalizedName = _localizationService.GetLocalized(manufacturer, x => x.Name, language.Id) + }; + + manufacturerDto.LocalizedNames.Add(localizedNameDto); + } + + return manufacturerDto; + } + + + public TaxCategoryDto PrepareTaxCategoryDTO(TaxCategory taxCategory) + { + var taxRateModel = new TaxCategoryDto() + { + Id = taxCategory.Id, + Name = taxCategory.Name, + DisplayOrder = taxCategory.DisplayOrder, + Rate = _settingService.GetSettingByKey(string.Format(Configurations.FixedRateSettingsKey, taxCategory.Id)) + }; + + return taxRateModel; + } + + } +} + + + +//protected ImageMappingDto PrepareProductImageDto(ProductPicture productPicture) +//{ +// ImageMappingDto imageMapping = null; + +// if (productPicture != null) +// { +// // We don't use the image from the passed dto directly +// // because the picture may be passed with src and the result should only include the base64 format. +// imageMapping = new ImageMappingDto +// { +// //Attachment = Convert.ToBase64String(picture.PictureBinary), +// Id = productPicture.Id, +// ProductId = productPicture.ProductId, +// PictureId = productPicture.PictureId, +// Position = productPicture.DisplayOrder, +// MimeType = productPicture.Picture.MimeType, +// Src = _pictureService.GetPictureUrl(productPicture.Picture) +// }; +// } + +// return imageMapping; +//} \ No newline at end of file diff --git "a/Nop.Plugin.Api/Helpers/IConfigMan\320\260gerHelper.cs" "b/Helpers/IConfigMan\320\260gerHelper.cs" similarity index 89% rename from "Nop.Plugin.Api/Helpers/IConfigMan\320\260gerHelper.cs" rename to "Helpers/IConfigMan\320\260gerHelper.cs" index b845f0b..d378166 100644 --- "a/Nop.Plugin.Api/Helpers/IConfigMan\320\260gerHelper.cs" +++ "b/Helpers/IConfigMan\320\260gerHelper.cs" @@ -1,4 +1,4 @@ -using Nop.Core.Data; +using Nop.Data; namespace Nop.Plugin.Api.Helpers { diff --git a/Nop.Plugin.Api/Helpers/ICustomerRolesHelper.cs b/Helpers/ICustomerRolesHelper.cs similarity index 100% rename from Nop.Plugin.Api/Helpers/ICustomerRolesHelper.cs rename to Helpers/ICustomerRolesHelper.cs diff --git a/Nop.Plugin.Api/Helpers/IDTOHelper.cs b/Helpers/IDTOHelper.cs similarity index 54% rename from Nop.Plugin.Api/Helpers/IDTOHelper.cs rename to Helpers/IDTOHelper.cs index 9f89596..e286c5f 100644 --- a/Nop.Plugin.Api/Helpers/IDTOHelper.cs +++ b/Helpers/IDTOHelper.cs @@ -1,32 +1,42 @@ -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Localization; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Stores; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.DTOs.Manufacturers; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.DTOs.ProductAttributes; -using Nop.Plugin.Api.DTOs.Products; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; -using Nop.Plugin.Api.DTOs.Stores; - -namespace Nop.Plugin.Api.Helpers -{ - public interface IDTOHelper - { - ProductDto PrepareProductDTO(Product product); - CategoryDto PrepareCategoryDTO(Category category); - OrderDto PrepareOrderDTO(Order order); - ShoppingCartItemDto PrepareShoppingCartItemDTO(ShoppingCartItem shoppingCartItem); - OrderItemDto PrepareOrderItemDTO(OrderItem orderItem); - StoreDto PrepareStoreDTO(Store store); - LanguageDto PrepateLanguageDto(Language language); - ProductAttributeDto PrepareProductAttributeDTO(ProductAttribute productAttribute); - ProductSpecificationAttributeDto PrepareProductSpecificationAttributeDto(ProductSpecificationAttribute productSpecificationAttribute); - SpecificationAttributeDto PrepareSpecificationAttributeDto(SpecificationAttribute specificationAttribute); - ManufacturerDto PrepareManufacturerDto(Manufacturer manufacturer); - } -} \ No newline at end of file +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Localization; +using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Stores; +using Nop.Core.Domain.Tax; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.DTO.Images; +using Nop.Plugin.Api.DTO.Languages; +using Nop.Plugin.Api.DTO.Manufacturers; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.DTO.Orders; +using Nop.Plugin.Api.DTO.ProductAttributes; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using Nop.Plugin.Api.DTO.SpecificationAttributes; +using Nop.Plugin.Api.DTO.Stores; +using Nop.Plugin.Api.DTO.TaxCategory; + +namespace Nop.Plugin.Api.Helpers +{ + public interface IDTOHelper + { + CustomerDto PrepareCustomerDTO(Customer customer); + ProductDto PrepareProductDTO(Product product); + CategoryDto PrepareCategoryDTO(Category category); + OrderDto PrepareOrderDTO(Order order); + ShoppingCartItemDto PrepareShoppingCartItemDTO(ShoppingCartItem shoppingCartItem); + OrderItemDto PrepareOrderItemDTO(OrderItem orderItem); + StoreDto PrepareStoreDTO(Store store); + LanguageDto PrepareLanguageDto(Language language); + ProductAttributeDto PrepareProductAttributeDTO(ProductAttribute productAttribute); + ProductSpecificationAttributeDto PrepareProductSpecificationAttributeDto(ProductSpecificationAttribute productSpecificationAttribute); + SpecificationAttributeDto PrepareSpecificationAttributeDto(SpecificationAttribute specificationAttribute); + ManufacturerDto PrepareManufacturerDto(Manufacturer manufacturer); + TaxCategoryDto PrepareTaxCategoryDTO(TaxCategory taxCategory); + ImageMappingDto PrepareProductPictureDTO(ProductPicture productPicture); + + } +} + diff --git a/Nop.Plugin.Api/Helpers/IJsonHelper.cs b/Helpers/IJsonHelper.cs similarity index 100% rename from Nop.Plugin.Api/Helpers/IJsonHelper.cs rename to Helpers/IJsonHelper.cs diff --git a/Nop.Plugin.Api/Helpers/IMappingHelper.cs b/Helpers/IMappingHelper.cs similarity index 100% rename from Nop.Plugin.Api/Helpers/IMappingHelper.cs rename to Helpers/IMappingHelper.cs diff --git a/Nop.Plugin.Api/Helpers/JTokenHelper.cs b/Helpers/JTokenHelper.cs similarity index 97% rename from Nop.Plugin.Api/Helpers/JTokenHelper.cs rename to Helpers/JTokenHelper.cs index cf96693..56ed6f6 100644 --- a/Nop.Plugin.Api/Helpers/JTokenHelper.cs +++ b/Helpers/JTokenHelper.cs @@ -1,71 +1,71 @@ -namespace Nop.Plugin.Api.Helpers -{ - using System.Collections.Generic; - using Newtonsoft.Json.Linq; - - public static class JTokenHelper - { - public static JToken RemoveEmptyChildrenAndFilterByFields(this JToken token, IList jsonFields, int level = 1) - { - if (token.Type == JTokenType.Object) - { - var copy = new JObject(); - - foreach (var prop in token.Children()) - { - var child = prop.Value; - - if (child.HasValues) - { - child = child.RemoveEmptyChildrenAndFilterByFields(jsonFields, level + 1); - } - - // In the current json structure, the first level of properties is level 3. - // If the level is > 3 ( meaning we are not on the first level of properties ), we should not check if the current field is containing into the list with fields, - // so we need to serialize it always. - var allowedFields = jsonFields.Contains(prop.Name.ToLowerInvariant()) || level > 3; - - // If the level == 3 ( meaning we are on the first level of properties ), we should not take into account if the current field is values, - // so we need to serialize it always. - var notEmpty = !child.IsEmptyOrDefault() || level == 1 || level == 3; - - if (notEmpty && allowedFields) - { - copy.Add(prop.Name, child); - } - } - - return copy; - } - - if (token.Type == JTokenType.Array) - { - var copy = new JArray(); - - foreach (var item in token.Children()) - { - var child = item; - - if (child.HasValues) - { - child = child.RemoveEmptyChildrenAndFilterByFields(jsonFields, level + 1); - } - - if (!child.IsEmptyOrDefault()) - { - copy.Add(child); - } - } - - return copy; - } - - return token; - } - - private static bool IsEmptyOrDefault(this JToken token) - { - return (token.Type == JTokenType.Array && !token.HasValues) || (token.Type == JTokenType.Object && !token.HasValues); - } - } +namespace Nop.Plugin.Api.Helpers +{ + using System.Collections.Generic; + using Newtonsoft.Json.Linq; + + public static class JTokenHelper + { + public static JToken RemoveEmptyChildrenAndFilterByFields(this JToken token, IList jsonFields, int level = 1) + { + if (token.Type == JTokenType.Object) + { + var copy = new JObject(); + + foreach (var prop in token.Children()) + { + var child = prop.Value; + + if (child.HasValues) + { + child = child.RemoveEmptyChildrenAndFilterByFields(jsonFields, level + 1); + } + + // In the current json structure, the first level of properties is level 3. + // If the level is > 3 ( meaning we are not on the first level of properties ), we should not check if the current field is containing into the list with fields, + // so we need to serialize it always. + var allowedFields = jsonFields.Contains(prop.Name.ToLowerInvariant()) || level > 3; + + // If the level == 3 ( meaning we are on the first level of properties ), we should not take into account if the current field is values, + // so we need to serialize it always. + var notEmpty = !child.IsEmptyOrDefault() || level == 1 || level == 3; + + if (notEmpty && allowedFields) + { + copy.Add(prop.Name, child); + } + } + + return copy; + } + + if (token.Type == JTokenType.Array) + { + var copy = new JArray(); + + foreach (var item in token.Children()) + { + var child = item; + + if (child.HasValues) + { + child = child.RemoveEmptyChildrenAndFilterByFields(jsonFields, level + 1); + } + + if (!child.IsEmptyOrDefault()) + { + copy.Add(child); + } + } + + return copy; + } + + return token; + } + + private static bool IsEmptyOrDefault(this JToken token) + { + return (token.Type == JTokenType.Array && !token.HasValues) || (token.Type == JTokenType.Object && !token.HasValues); + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Helpers/JsonHelper.cs b/Helpers/JsonHelper.cs similarity index 100% rename from Nop.Plugin.Api/Helpers/JsonHelper.cs rename to Helpers/JsonHelper.cs diff --git a/Nop.Plugin.Api/Helpers/MappingHelper.cs b/Helpers/MappingHelper.cs similarity index 97% rename from Nop.Plugin.Api/Helpers/MappingHelper.cs rename to Helpers/MappingHelper.cs index 54aa952..a5e6ba1 100644 --- a/Nop.Plugin.Api/Helpers/MappingHelper.cs +++ b/Helpers/MappingHelper.cs @@ -1,261 +1,261 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.Factories; - -namespace Nop.Plugin.Api.Helpers -{ - // TODO: Think of moving the mapping helper in the delta folder - public class MappingHelper : IMappingHelper - { - public void Merge(object source, object destination) - { - var sourcePropertyValuePairs = source.GetType() - .GetProperties() - .ToDictionary(property => property.Name, property => property.GetValue(source)); - - SetValues(sourcePropertyValuePairs, destination, destination.GetType(),null); - } - - public void SetValues(Dictionary propertyNameValuePairs, object objectToBeUpdated, - Type propertyType, Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections = false) - { - objectPropertyNameValuePairs?.Add(objectToBeUpdated, propertyNameValuePairs); - - foreach (var propertyNameValuePair in propertyNameValuePairs) - { - SetValue(objectToBeUpdated, propertyNameValuePair, objectPropertyNameValuePairs, handleComplexTypeCollections); - } - } - - // Used in the SetValue private method and also in the Delta. - private void ConvertAndSetValueIfValid(object objectToBeUpdated, PropertyInfo objectProperty, object propertyValue) - { - var converter = TypeDescriptor.GetConverter(objectProperty.PropertyType); - - var propertyValueAsString = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", propertyValue); - - if (converter.IsValid(propertyValueAsString)) - { - var convertedValue = converter.ConvertFromInvariantString(propertyValueAsString); - - objectProperty.SetValue(objectToBeUpdated, convertedValue); - } - } - - private void SetValue(object objectToBeUpdated, KeyValuePair propertyNameValuePair, Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) - { - var propertyName = propertyNameValuePair.Key; - var propertyValue = propertyNameValuePair.Value; - - var propertyToUpdate = objectToBeUpdated.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); - - if (propertyToUpdate != null) - { - // This case handles nested properties. - if (propertyValue != null && propertyValue is Dictionary) - { - var valueToUpdate = propertyToUpdate.GetValue(objectToBeUpdated); - - if (valueToUpdate == null) - { - // Check if there is registered factory for this type. - var factoryType = typeof(IFactory<>); - var factoryTypeForCurrentProperty = factoryType.MakeGenericType(new Type[] { propertyToUpdate.PropertyType }); - var initializerFactory = ((NopEngine)EngineContext.Current).ServiceProvider.GetService(factoryTypeForCurrentProperty); - - if (initializerFactory != null) - { - var initializeMethod = factoryTypeForCurrentProperty.GetMethod("Initialize"); - - valueToUpdate = initializeMethod.Invoke(initializerFactory, null); - } - else - { - valueToUpdate = Activator.CreateInstance(propertyToUpdate.PropertyType); - } - - propertyToUpdate.SetValue(objectToBeUpdated, valueToUpdate); - } - - // We need to use GetValue method to get the actual instance of the jsonProperty. objectProperty is the jsonProperty info. - SetValues((Dictionary)propertyValue, valueToUpdate, - propertyToUpdate.PropertyType, objectPropertyNameValuePairs); - // We expect the nested properties to be classes which are refrence types. - return; - } - // This case hadles collections. - else if (propertyValue != null && propertyValue is ICollection) - { - var propertyValueAsCollection = propertyValue as ICollection; - - var collectionElementsType = propertyToUpdate.PropertyType.GetGenericArguments()[0]; - var collection = propertyToUpdate.GetValue(objectToBeUpdated); - - if (collection == null) - { - collection = CreateEmptyList(collectionElementsType); - propertyToUpdate.SetValue(objectToBeUpdated, collection); - } - - //this is a hack to fix a bug when "collection" cannot be cast to IList (ex: it's a HashSet for Order.OrderItems) - var collectionAsList = collection as IList; - if (collectionAsList == null) - { - collectionAsList = CreateEmptyList(collectionElementsType); - - var collectionAsEnumerable = collection as IEnumerable; - foreach (var collectionItem in collectionAsEnumerable) - { - collectionAsList.Add(collectionItem); - } - - collection = collectionAsList; - propertyToUpdate.SetValue(objectToBeUpdated, collection); - } - - foreach (var item in propertyValueAsCollection) - { - if (collectionElementsType.Namespace != "System") - { - if (handleComplexTypeCollections) - { - AddOrUpdateComplexItemInCollection(item as Dictionary, - collection as IList, - collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); - } - } - else - { - AddBaseItemInCollection(item, collection as IList, collectionElementsType); - } - } - - return; - } - - // This is where the new value is beeing set to the object jsonProperty using the SetValue function part of System.Reflection. - if (propertyValue == null) - { - propertyToUpdate.SetValue(objectToBeUpdated, null); - } - else if (propertyValue is IConvertible) - { - ConvertAndSetValueIfValid(objectToBeUpdated, propertyToUpdate, propertyValue); - // otherwise ignore the passed value. - } - else - { - propertyToUpdate.SetValue(objectToBeUpdated, propertyValue); - } - } - } - - private void AddBaseItemInCollection(object newItem, IList collection, Type collectionElementsType) - { - var converter = TypeDescriptor.GetConverter(collectionElementsType); - - var newItemValueToString = newItem.ToString(); - - if (converter.IsValid(newItemValueToString)) - { - collection.Add(converter.ConvertFrom(newItemValueToString)); - } - } - - private void AddOrUpdateComplexItemInCollection(Dictionary newProperties, IList collection, Type collectionElementsType, - Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) - { - if (newProperties.ContainsKey("Id")) - { - // Every element in collection, that is not System type should have an id. - var id = int.Parse(newProperties["Id"].ToString()); - - object itemToBeUpdated = null; - - // Check if there is already an item with this id in the collection. - foreach (var item in collection) - { - if (int.Parse(item.GetType() - .GetProperty("Id", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) - .GetValue(item) - .ToString()) == id) - { - itemToBeUpdated = item; - break; - } - } - - if (itemToBeUpdated == null) - { - // We should create a new item and put it in the collection. - AddNewItemInCollection(newProperties, collection, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); - } - else - { - // We should update the existing element. - SetValues(newProperties, itemToBeUpdated, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); - } - } - // It is a new item. - else - { - AddNewItemInCollection(newProperties, collection, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); - } - } - - private void AddNewItemInCollection(Dictionary newProperties, IList collection, Type collectionElementsType,Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) - { - var newInstance = Activator.CreateInstance(collectionElementsType); - - var properties = collectionElementsType.GetProperties(); - - SetEveryDatePropertyThatIsNotSetToDateTimeUtcNow(newProperties, properties); - - SetValues(newProperties, newInstance, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); - - collection.Add(newInstance); - } - - private IList CreateEmptyList(Type listItemType) - { - var listType = typeof(List<>); - var constructedListType = listType.MakeGenericType(listItemType); - var list = Activator.CreateInstance(constructedListType); - - return list as IList; - } - - // We need this method, because the default value of DateTime is not in the sql server DateTime range and we will get an exception if we use it. - private void SetEveryDatePropertyThatIsNotSetToDateTimeUtcNow(Dictionary newProperties, PropertyInfo[] properties) - { - foreach (var property in properties) - { - if (property.PropertyType == typeof(DateTime)) - { - var keyFound = false; - - // We need to loop through the keys, because the key may contain underscores in its name, which won't match the jsonProperty name. - foreach (var key in newProperties.Keys) - { - if (key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase)) - { - keyFound = true; - break; - } - } - - if (!keyFound) - { - // Create the item with the DateTime.NowUtc. - newProperties.Add(property.Name, DateTime.UtcNow); - } - } - } - } - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Factories; + +namespace Nop.Plugin.Api.Helpers +{ + // TODO: Think of moving the mapping helper in the delta folder + public class MappingHelper : IMappingHelper + { + public void Merge(object source, object destination) + { + var sourcePropertyValuePairs = source.GetType() + .GetProperties() + .ToDictionary(property => property.Name, property => property.GetValue(source)); + + SetValues(sourcePropertyValuePairs, destination, destination.GetType(),null); + } + + public void SetValues(Dictionary propertyNameValuePairs, object objectToBeUpdated, + Type propertyType, Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections = false) + { + objectPropertyNameValuePairs?.Add(objectToBeUpdated, propertyNameValuePairs); + + foreach (var propertyNameValuePair in propertyNameValuePairs) + { + SetValue(objectToBeUpdated, propertyNameValuePair, objectPropertyNameValuePairs, handleComplexTypeCollections); + } + } + + // Used in the SetValue private method and also in the Delta. + private void ConvertAndSetValueIfValid(object objectToBeUpdated, PropertyInfo objectProperty, object propertyValue) + { + var converter = TypeDescriptor.GetConverter(objectProperty.PropertyType); + + var propertyValueAsString = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", propertyValue); + + if (converter.IsValid(propertyValueAsString)) + { + var convertedValue = converter.ConvertFromInvariantString(propertyValueAsString); + + objectProperty.SetValue(objectToBeUpdated, convertedValue); + } + } + + private void SetValue(object objectToBeUpdated, KeyValuePair propertyNameValuePair, Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) + { + var propertyName = propertyNameValuePair.Key; + var propertyValue = propertyNameValuePair.Value; + + var propertyToUpdate = objectToBeUpdated.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); + + if (propertyToUpdate != null) + { + // This case handles nested properties. + if (propertyValue != null && propertyValue is Dictionary) + { + var valueToUpdate = propertyToUpdate.GetValue(objectToBeUpdated); + + if (valueToUpdate == null) + { + // Check if there is registered factory for this type. + var factoryType = typeof(IFactory<>); + var factoryTypeForCurrentProperty = factoryType.MakeGenericType(new Type[] { propertyToUpdate.PropertyType }); + var initializerFactory = ((NopEngine)EngineContext.Current).ServiceProvider.GetService(factoryTypeForCurrentProperty); + + if (initializerFactory != null) + { + var initializeMethod = factoryTypeForCurrentProperty.GetMethod("Initialize"); + + valueToUpdate = initializeMethod.Invoke(initializerFactory, null); + } + else + { + valueToUpdate = Activator.CreateInstance(propertyToUpdate.PropertyType); + } + + propertyToUpdate.SetValue(objectToBeUpdated, valueToUpdate); + } + + // We need to use GetValue method to get the actual instance of the jsonProperty. objectProperty is the jsonProperty info. + SetValues((Dictionary)propertyValue, valueToUpdate, + propertyToUpdate.PropertyType, objectPropertyNameValuePairs); + // We expect the nested properties to be classes which are refrence types. + return; + } + // This case hadles collections. + else if (propertyValue != null && propertyValue is ICollection) + { + var propertyValueAsCollection = propertyValue as ICollection; + + var collectionElementsType = propertyToUpdate.PropertyType.GetGenericArguments()[0]; + var collection = propertyToUpdate.GetValue(objectToBeUpdated); + + if (collection == null) + { + collection = CreateEmptyList(collectionElementsType); + propertyToUpdate.SetValue(objectToBeUpdated, collection); + } + + //this is a hack to fix a bug when "collection" cannot be cast to IList (ex: it's a HashSet for Order.OrderItems) + var collectionAsList = collection as IList; + if (collectionAsList == null) + { + collectionAsList = CreateEmptyList(collectionElementsType); + + var collectionAsEnumerable = collection as IEnumerable; + foreach (var collectionItem in collectionAsEnumerable) + { + collectionAsList.Add(collectionItem); + } + + collection = collectionAsList; + propertyToUpdate.SetValue(objectToBeUpdated, collection); + } + + foreach (var item in propertyValueAsCollection) + { + if (collectionElementsType.Namespace != "System") + { + if (handleComplexTypeCollections) + { + AddOrUpdateComplexItemInCollection(item as Dictionary, + collection as IList, + collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); + } + } + else + { + AddBaseItemInCollection(item, collection as IList, collectionElementsType); + } + } + + return; + } + + // This is where the new value is beeing set to the object jsonProperty using the SetValue function part of System.Reflection. + if (propertyValue == null) + { + propertyToUpdate.SetValue(objectToBeUpdated, null); + } + else if (propertyValue is IConvertible) + { + ConvertAndSetValueIfValid(objectToBeUpdated, propertyToUpdate, propertyValue); + // otherwise ignore the passed value. + } + else + { + propertyToUpdate.SetValue(objectToBeUpdated, propertyValue); + } + } + } + + private void AddBaseItemInCollection(object newItem, IList collection, Type collectionElementsType) + { + var converter = TypeDescriptor.GetConverter(collectionElementsType); + + var newItemValueToString = newItem.ToString(); + + if (converter.IsValid(newItemValueToString)) + { + collection.Add(converter.ConvertFrom(newItemValueToString)); + } + } + + private void AddOrUpdateComplexItemInCollection(Dictionary newProperties, IList collection, Type collectionElementsType, + Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) + { + if (newProperties.ContainsKey("Id")) + { + // Every element in collection, that is not System type should have an id. + var id = int.Parse(newProperties["Id"].ToString()); + + object itemToBeUpdated = null; + + // Check if there is already an item with this id in the collection. + foreach (var item in collection) + { + if (int.Parse(item.GetType() + .GetProperty("Id", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) + .GetValue(item) + .ToString()) == id) + { + itemToBeUpdated = item; + break; + } + } + + if (itemToBeUpdated == null) + { + // We should create a new item and put it in the collection. + AddNewItemInCollection(newProperties, collection, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); + } + else + { + // We should update the existing element. + SetValues(newProperties, itemToBeUpdated, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); + } + } + // It is a new item. + else + { + AddNewItemInCollection(newProperties, collection, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); + } + } + + private void AddNewItemInCollection(Dictionary newProperties, IList collection, Type collectionElementsType,Dictionary objectPropertyNameValuePairs, bool handleComplexTypeCollections) + { + var newInstance = Activator.CreateInstance(collectionElementsType); + + var properties = collectionElementsType.GetProperties(); + + SetEveryDatePropertyThatIsNotSetToDateTimeUtcNow(newProperties, properties); + + SetValues(newProperties, newInstance, collectionElementsType, objectPropertyNameValuePairs, handleComplexTypeCollections); + + collection.Add(newInstance); + } + + private IList CreateEmptyList(Type listItemType) + { + var listType = typeof(List<>); + var constructedListType = listType.MakeGenericType(listItemType); + var list = Activator.CreateInstance(constructedListType); + + return list as IList; + } + + // We need this method, because the default value of DateTime is not in the sql server DateTime range and we will get an exception if we use it. + private void SetEveryDatePropertyThatIsNotSetToDateTimeUtcNow(Dictionary newProperties, PropertyInfo[] properties) + { + foreach (var property in properties) + { + if (property.PropertyType == typeof(DateTime)) + { + var keyFound = false; + + // We need to loop through the keys, because the key may contain underscores in its name, which won't match the jsonProperty name. + foreach (var key in newProperties.Keys) + { + if (key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase)) + { + keyFound = true; + break; + } + } + + if (!keyFound) + { + // Create the item with the DateTime.NowUtc. + newProperties.Add(property.Name, DateTime.UtcNow); + } + } + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Helpers/ReflectionHelper.cs b/Helpers/ReflectionHelper.cs similarity index 97% rename from Nop.Plugin.Api/Helpers/ReflectionHelper.cs rename to Helpers/ReflectionHelper.cs index f593736..b45a4fd 100644 --- a/Nop.Plugin.Api/Helpers/ReflectionHelper.cs +++ b/Helpers/ReflectionHelper.cs @@ -1,24 +1,24 @@ -using System; -using System.Reflection; -using Newtonsoft.Json; - -namespace Nop.Plugin.Api.Helpers -{ - public static class ReflectionHelper - { - public static bool HasProperty(string propertyName, Type type) - { - return type.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null; - } - - public static JsonObjectAttribute GetJsonObjectAttribute(Type objectType) - { - var jsonObject = objectType.GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute; - - return jsonObject; - } - - public static Type GetGenericElementType(Type type) - => type.HasElementType ? type.GetElementType() : type.GetTypeInfo().GenericTypeArguments[0]; - } +using System; +using System.Reflection; +using Newtonsoft.Json; + +namespace Nop.Plugin.Api.Helpers +{ + public static class ReflectionHelper + { + public static bool HasProperty(string propertyName, Type type) + { + return type.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null; + } + + public static JsonObjectAttribute GetJsonObjectAttribute(Type objectType) + { + var jsonObject = objectType.GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute; + + return jsonObject; + } + + public static Type GetGenericElementType(Type type) + => type.HasElementType ? type.GetElementType() : type.GetTypeInfo().GenericTypeArguments[0]; + } } \ No newline at end of file diff --git a/Infrastructure/ApiPlugin.cs b/Infrastructure/ApiPlugin.cs new file mode 100644 index 0000000..da56176 --- /dev/null +++ b/Infrastructure/ApiPlugin.cs @@ -0,0 +1,139 @@ +using Nop.Core; +using Nop.Core.Domain.Customers; +using Nop.Plugin.Api.Domain; +using Nop.Services.Configuration; +using Nop.Services.Customers; +using Nop.Services.Localization; +using Nop.Services.Plugins; +using Nop.Web.Framework.Menu; + +namespace Nop.Plugin.Api.Infrastructure +{ + public class ApiPlugin : BasePlugin, IAdminMenuPlugin + { + private readonly ICustomerService _customerService; + private readonly ILocalizationService _localizationService; + private readonly ISettingService _settingService; + private readonly IWebHelper _webHelper; + private readonly IWorkContext _workContext; + + public ApiPlugin( + ISettingService settingService, + IWorkContext workContext, + ICustomerService customerService, + ILocalizationService localizationService, + IWebHelper webHelper) + { + _settingService = settingService; + _workContext = workContext; + _customerService = customerService; + _localizationService = localizationService; + _webHelper = webHelper; + } + + public override void Install() + { + //locales + + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api", "Api plugin"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.ManageClients", "Manage Api Clients"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Configure", "Configure Web Api"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.GeneralSettings", "General Settings"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableApi", "Enable Api"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableApi.Hint", "By checking this settings you can Enable/Disable the Web Api"); + + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Title", "API"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Settings.Title", "Settings"); + + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Page.Settings.Title", "Api Settings"); + + + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Settings.GeneralSettingsTitle", "General Settings"); + _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Edit", "Edit"); + + _localizationService.AddOrUpdatePluginLocaleResource("Api.Categories.Fields.Id.Invalid", "Id is invalid"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidPropertyType", "Invalid Property Type"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidType", "Invalid {0} type"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidRequest", "Invalid request"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidRootProperty", "Invalid root property"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.NoJsonProvided", "No Json provided"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidJsonFormat", "Json format is invalid"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageAttachmentFormat", "Invalid image attachment base64 format"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageSrc", "Invalid image source"); + _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageSrcType", "You have provided an invalid image source/attachment "); + + _settingService.SaveSetting(new ApiSettings()); + + var apiRole = _customerService.GetCustomerRoleBySystemName(Constants.Roles.ApiRoleSystemName); + + if (apiRole == null) + { + apiRole = new CustomerRole + { + Name = Constants.Roles.ApiRoleName, + Active = true, + SystemName = Constants.Roles.ApiRoleSystemName + }; + + _customerService.InsertCustomerRole(apiRole); + } + else if (apiRole.Active == false) + { + apiRole.Active = true; + _customerService.UpdateCustomerRole(apiRole); + } + + + base.Install(); + + // Changes to Web.Config trigger application restart. + // This doesn't appear to affect the Install function, but just to be safe we will made web.config changes after the plugin was installed. + //_webConfigMangerHelper.AddConfiguration(); + } + + public override void Uninstall() + { + //locales + _localizationService.DeletePluginLocaleResources("Plugins.Api"); + + var apiRole = _customerService.GetCustomerRoleBySystemName(Constants.Roles.ApiRoleSystemName); + if (apiRole != null) + { + apiRole.Active = false; + _customerService.UpdateCustomerRole(apiRole); + } + + + base.Uninstall(); + } + + public void ManageSiteMap(SiteMapNode rootNode) + { + var pluginMenuName = _localizationService.GetResource("Plugins.Api.Admin.Menu.Title", _workContext.WorkingLanguage.Id, defaultValue: "API"); + + var settingsMenuName = _localizationService.GetResource("Plugins.Api.Admin.Menu.Settings.Title", _workContext.WorkingLanguage.Id, defaultValue: "API"); + + const string adminUrlPart = "Admin/"; + + var pluginMainMenu = new SiteMapNode + { + Title = pluginMenuName, + Visible = true, + SystemName = "Api-Main-Menu", + IconClass = "fa-genderless" + }; + + pluginMainMenu.ChildNodes.Add(new SiteMapNode + { + Title = settingsMenuName, + Url = _webHelper.GetStoreLocation() + adminUrlPart + "ApiAdmin/Settings", + Visible = true, + SystemName = "Api-Settings-Menu", + IconClass = "fa-genderless" + }); + + + rootNode.ChildNodes.Add(pluginMainMenu); + } + } +} diff --git a/Infrastructure/ApiStartup.cs b/Infrastructure/ApiStartup.cs new file mode 100644 index 0000000..c8f2c25 --- /dev/null +++ b/Infrastructure/ApiStartup.cs @@ -0,0 +1,128 @@ +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Text; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Rewrite; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Authorization.Policies; +using Nop.Plugin.Api.Authorization.Requirements; +using Nop.Plugin.Api.Configuration; +using Nop.Web.Framework.Infrastructure.Extensions; + +namespace Nop.Plugin.Api.Infrastructure +{ + public class ApiStartup : INopStartup + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + var apiConfigSection = configuration.GetSection("Api"); + + if (apiConfigSection != null) + { + var apiConfig = services.ConfigureStartupConfig(apiConfigSection); + + if (!string.IsNullOrEmpty(apiConfig.SecurityKey)) + { + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => + { + + jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(apiConfig.SecurityKey)), + ValidateIssuer = false, // ValidIssuer = "The name of the issuer", + ValidateAudience = false, // ValidAudience = "The name of the audience", + ValidateLifetime = true, // validate the expiration and not before values in the token + ClockSkew = TimeSpan.FromMinutes(apiConfig.AllowedClockSkewInMinutes) + }; + }); + + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + AddAuthorizationPipeline(services); + + } + } + + } + + public void Configure(IApplicationBuilder app) + { + var rewriteOptions = new RewriteOptions() + .AddRewrite("api/token", "/token", true); + + app.UseRewriter(rewriteOptions); + + app.UseCors(x => x.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader()); + + + app.MapWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), + a => + { + + a.Use(async (context, next) => + { + Console.WriteLine("API Call"); + context.Request.EnableBuffering(); + await next(); + }); + + //a.UseExceptionHandler("/api/error/500/Error"); + + a + .UseRouting() + .UseAuthentication() + .UseAuthorization() + .UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + } + ); + } + + public int Order => 1; + + private static void AddAuthorizationPipeline(IServiceCollection services) + { + services.Configure(options => + { + options.AllowSynchronousIO = true; + }).Configure(options => + { + options.AllowSynchronousIO = true; + }); + + services.AddAuthorization(options => + { + options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, + policy => + { + policy.Requirements.Add(new ActiveApiPluginRequirement()); + policy.Requirements.Add(new AuthorizationSchemeRequirement()); + policy.Requirements.Add(new CustomerRoleRequirement()); + policy.RequireAuthenticatedUser(); + }); + }); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + } + } +} diff --git a/Infrastructure/Constants.cs b/Infrastructure/Constants.cs new file mode 100644 index 0000000..ac5628d --- /dev/null +++ b/Infrastructure/Constants.cs @@ -0,0 +1,56 @@ +using Nop.Core.Caching; + +namespace Nop.Plugin.Api.Infrastructure +{ + public static class Constants + { + public static class Roles + { + public const string ApiRoleSystemName = "ApiUserRole"; + + public const string ApiRoleName = "Api Users"; + } + + public static class ViewNames + { + public const string AdminLayout = "_AdminLayout"; + public const string AdminApiSettings = "~/Plugins/Nop.Plugin.Api/Views/Settings.cshtml"; + public const string AdminApiClientsCreateOrUpdate = "~/Plugins/Nop.Plugin.Api/Views/Clients/CreateOrUpdate.cshtml"; + public const string AdminApiClientsSettings = "~/Plugins/Nop.Plugin.Api/Views/Clients/ClientSettings.cshtml"; + public const string AdminApiClientsList = "~/Plugins/Nop.Plugin.Api/Views/Clients/List.cshtml"; + public const string AdminApiClientsCreate = "~/Plugins/Nop.Plugin.Api/Views/Clients/Create.cshtml"; + public const string AdminApiClientsEdit = "~/Plugins/Nop.Plugin.Api/Views/Clients/Edit.cshtml"; + } + + public static class Configurations + { + public const int DefaultAccessTokenExpirationInDays = 3650; // 10 years + + + public const int DefaultLimit = 50; + public const int DefaultPageValue = 1; + public const int DefaultSinceId = 0; + public const int DefaultCustomerId = 0; + public const string DefaultOrder = "Id"; + public const int MaxLimit = 250; + + public const int MinLimit = 1; + + + + public const string PublishedStatus = "published"; + public const string UnpublishedStatus = "unpublished"; + public const string AnyStatus = "any"; + + + public const string FixedRateSettingsKey = "Tax.TaxProvider.FixedOrByCountryStateZip.TaxCategoryId{0}"; + + //public const string PublishedStatus = "published"; + //public const string UnpublishedStatus = "unpublished"; + //public const string AnyStatus = "any"; + public static CacheKey JsonTypeMapsPattern => new CacheKey("json.maps"); + + public static CacheKey NEWSLETTER_SUBSCRIBERS_KEY = new CacheKey("Nop.api.newslettersubscribers"); + } + } +} diff --git a/Nop.Plugin.Api/Infrastructure/DependencyRegister.cs b/Infrastructure/DependencyRegister.cs similarity index 78% rename from Nop.Plugin.Api/Infrastructure/DependencyRegister.cs rename to Infrastructure/DependencyRegister.cs index 63a5348..5d4f400 100644 --- a/Nop.Plugin.Api/Infrastructure/DependencyRegister.cs +++ b/Infrastructure/DependencyRegister.cs @@ -1,99 +1,89 @@ -using Autofac; -using Nop.Core.Configuration; -using Nop.Core.Infrastructure; -using Nop.Core.Infrastructure.DependencyManagement; -using Nop.Plugin.Api.Services; -using Nop.Web.Framework.Infrastructure.Extensions; - -namespace Nop.Plugin.Api.Infrastructure -{ - using Autofac.Core; - using Microsoft.AspNetCore.Http; - using Nop.Core.Domain.Catalog; - using Nop.Core.Domain.Common; - using Nop.Core.Domain.Customers; - using Nop.Core.Domain.Orders; - using Nop.Plugin.Api.Converters; - using Nop.Plugin.Api.Data; - using Nop.Plugin.Api.Factories; - using Nop.Plugin.Api.Helpers; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.ModelBinders; - using Nop.Plugin.Api.Validators; - //using Nop.Plugin.Api.WebHooks; - using System; - using System.Collections.Generic; - - public class DependencyRegister : IDependencyRegistrar - { - public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config) - { - RegisterPluginServices(builder); - - RegisterModelBinders(builder); - } - - private void RegisterModelBinders(ContainerBuilder builder) - { - builder.RegisterGeneric(typeof(ParametersModelBinder<>)).InstancePerLifetimeScope(); - builder.RegisterGeneric(typeof(JsonModelBinder<>)).InstancePerLifetimeScope(); - } - - private void RegisterPluginServices(ContainerBuilder builder) - { - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - //TODO: Upgrade 4.1. Check this! - //builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - - //TODO: Upgrade 4.1. Check this! - //builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - builder.RegisterType().As>().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType>().SingleInstance(); - } - - public virtual int Order - { - get { return Int16.MaxValue; } - } - } +using Autofac; +using Nop.Core.Configuration; +using Nop.Core.Infrastructure; +using Nop.Core.Infrastructure.DependencyManagement; +using Nop.Plugin.Api.Services; +using Microsoft.AspNetCore.Http; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Common; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Orders; +using Nop.Plugin.Api.Converters; +using Nop.Plugin.Api.Factories; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.JSON.Serializers; +using Nop.Plugin.Api.ModelBinders; +using Nop.Plugin.Api.Validators; +//using Nop.Plugin.Api.WebHooks; +using System; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Infrastructure +{ + + public class DependencyRegister : IDependencyRegistrar + { + public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config) + { + RegisterPluginServices(builder); + + RegisterModelBinders(builder); + } + + private void RegisterModelBinders(ContainerBuilder builder) + { + builder.RegisterGeneric(typeof(ParametersModelBinder<>)).InstancePerLifetimeScope(); + builder.RegisterGeneric(typeof(JsonModelBinder<>)).InstancePerLifetimeScope(); + } + + private void RegisterPluginServices(ContainerBuilder builder) + { + + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + builder.RegisterType().As>().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().SingleInstance(); + + builder.RegisterType>().SingleInstance(); + } + + public virtual int Order + { + get { return Int16.MaxValue; } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/JSON/ActionResults/ErrorActionResult.cs b/JSON/ActionResults/ErrorActionResult.cs similarity index 96% rename from Nop.Plugin.Api/JSON/ActionResults/ErrorActionResult.cs rename to JSON/ActionResults/ErrorActionResult.cs index da8f3b9..0e79378 100644 --- a/Nop.Plugin.Api/JSON/ActionResults/ErrorActionResult.cs +++ b/JSON/ActionResults/ErrorActionResult.cs @@ -1,41 +1,41 @@ -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace Nop.Plugin.Api.JSON.ActionResults -{ - using System; - using System.IO; - using System.Text; - using Microsoft.AspNetCore.WebUtilities; - - public class ErrorActionResult : IActionResult - { - private readonly string _jsonString; - private readonly HttpStatusCode _statusCode; - - public ErrorActionResult(string jsonString, HttpStatusCode statusCode) - { - _jsonString = jsonString; - _statusCode = statusCode; - } - - public Task ExecuteResultAsync(ActionContext context) - { - if (context == null) - throw new ArgumentNullException(nameof(context)); - - var response = context.HttpContext.Response; - - response.StatusCode = (int)_statusCode; - response.ContentType = "application/json"; - - using (TextWriter writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) - { - writer.Write(_jsonString); - } - - return Task.CompletedTask; - } - } +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace Nop.Plugin.Api.JSON.ActionResults +{ + using System; + using System.IO; + using System.Text; + using Microsoft.AspNetCore.WebUtilities; + + public class ErrorActionResult : IActionResult + { + private readonly string _jsonString; + private readonly HttpStatusCode _statusCode; + + public ErrorActionResult(string jsonString, HttpStatusCode statusCode) + { + _jsonString = jsonString; + _statusCode = statusCode; + } + + public Task ExecuteResultAsync(ActionContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + var response = context.HttpContext.Response; + + response.StatusCode = (int)_statusCode; + response.ContentType = "application/json"; + + using (TextWriter writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) + { + writer.Write(_jsonString); + } + + return Task.CompletedTask; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/JSON/ActionResults/RawJsonActionResult.cs b/JSON/ActionResults/RawJsonActionResult.cs similarity index 96% rename from Nop.Plugin.Api/JSON/ActionResults/RawJsonActionResult.cs rename to JSON/ActionResults/RawJsonActionResult.cs index 0e8e1d6..63ee5e2 100644 --- a/Nop.Plugin.Api/JSON/ActionResults/RawJsonActionResult.cs +++ b/JSON/ActionResults/RawJsonActionResult.cs @@ -1,42 +1,42 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace Nop.Plugin.Api.JSON.ActionResults -{ - using System; - using System.IO; - using System.Text; - using Microsoft.AspNetCore.WebUtilities; - - // TODO: Move to BaseApiController as method. - public class RawJsonActionResult : IActionResult - { - private readonly string _jsonString; - - public RawJsonActionResult(object value) - { - if (value != null) - { - _jsonString = value.ToString(); - } - } - - public Task ExecuteResultAsync(ActionContext context) - { - if (context == null) - throw new ArgumentNullException(nameof(context)); - - var response = context.HttpContext.Response; - - response.StatusCode = 200; - response.ContentType = "application/json"; - - using (TextWriter writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) - { - writer.Write(_jsonString); - } - - return Task.CompletedTask; - } - } -} +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace Nop.Plugin.Api.JSON.ActionResults +{ + using System; + using System.IO; + using System.Text; + using Microsoft.AspNetCore.WebUtilities; + + // TODO: Move to BaseApiController as method. + public class RawJsonActionResult : IActionResult + { + private readonly string _jsonString; + + public RawJsonActionResult(object value) + { + if (value != null) + { + _jsonString = value.ToString(); + } + } + + public Task ExecuteResultAsync(ActionContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + var response = context.HttpContext.Response; + + response.StatusCode = 200; + response.ContentType = "application/json"; + + using (TextWriter writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) + { + writer.Write(_jsonString); + } + + return Task.CompletedTask; + } + } +} diff --git a/Nop.Plugin.Api/JSON/Serializers/IJsonFieldsSerializer.cs b/JSON/Serializers/IJsonFieldsSerializer.cs similarity index 85% rename from Nop.Plugin.Api/JSON/Serializers/IJsonFieldsSerializer.cs rename to JSON/Serializers/IJsonFieldsSerializer.cs index cb0b6d7..3f1e2cd 100644 --- a/Nop.Plugin.Api/JSON/Serializers/IJsonFieldsSerializer.cs +++ b/JSON/Serializers/IJsonFieldsSerializer.cs @@ -1,6 +1,6 @@ namespace Nop.Plugin.Api.JSON.Serializers { - using Nop.Plugin.Api.DTOs; + using Nop.Plugin.Api.DTO; public interface IJsonFieldsSerializer { diff --git a/Nop.Plugin.Api/JSON/Serializers/JsonFieldsSerializer.cs b/JSON/Serializers/JsonFieldsSerializer.cs similarity index 95% rename from Nop.Plugin.Api/JSON/Serializers/JsonFieldsSerializer.cs rename to JSON/Serializers/JsonFieldsSerializer.cs index 45a7b6d..8d67562 100644 --- a/Nop.Plugin.Api/JSON/Serializers/JsonFieldsSerializer.cs +++ b/JSON/Serializers/JsonFieldsSerializer.cs @@ -1,61 +1,61 @@ -namespace Nop.Plugin.Api.JSON.Serializers -{ - using System; - using System.Collections.Generic; - using System.Linq; - using Newtonsoft.Json.Linq; - using Nop.Plugin.Api.DTOs; - using Nop.Plugin.Api.Helpers; - - public class JsonFieldsSerializer : IJsonFieldsSerializer - { - public string Serialize(ISerializableObject objectToSerialize, string jsonFields) - { - if (objectToSerialize == null) - { - throw new ArgumentNullException(nameof(objectToSerialize)); - } - - IList fieldsList = null; - - if (!string.IsNullOrEmpty(jsonFields)) - { - var primaryPropertyName = objectToSerialize.GetPrimaryPropertyName(); - - fieldsList = GetPropertiesIntoList(jsonFields); - - // Always add the root manually - fieldsList.Add(primaryPropertyName); - } - - var json = Serialize(objectToSerialize, fieldsList); - - return json; - } - - private string Serialize(object objectToSerialize, IList jsonFields = null) - { - var jToken = JToken.FromObject(objectToSerialize); - - if (jsonFields != null) - { - jToken = jToken.RemoveEmptyChildrenAndFilterByFields(jsonFields); - } - - var jTokenResult = jToken.ToString(); - - return jTokenResult; - } - - private IList GetPropertiesIntoList(string fields) - { - IList properties = fields.ToLowerInvariant() - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(x => x.Trim()) - .Distinct() - .ToList(); - - return properties; - } - } +namespace Nop.Plugin.Api.JSON.Serializers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json.Linq; + using Nop.Plugin.Api.DTO; + using Nop.Plugin.Api.Helpers; + + public class JsonFieldsSerializer : IJsonFieldsSerializer + { + public string Serialize(ISerializableObject objectToSerialize, string jsonFields) + { + if (objectToSerialize == null) + { + throw new ArgumentNullException(nameof(objectToSerialize)); + } + + IList fieldsList = null; + + if (!string.IsNullOrEmpty(jsonFields)) + { + var primaryPropertyName = objectToSerialize.GetPrimaryPropertyName(); + + fieldsList = GetPropertiesIntoList(jsonFields); + + // Always add the root manually + fieldsList.Add(primaryPropertyName); + } + + var json = Serialize(objectToSerialize, fieldsList); + + return json; + } + + private string Serialize(object objectToSerialize, IList jsonFields = null) + { + var jToken = JToken.FromObject(objectToSerialize); + + if (jsonFields != null) + { + jToken = jToken.RemoveEmptyChildrenAndFilterByFields(jsonFields); + } + + var jTokenResult = jToken.ToString(); + + return jTokenResult; + } + + private IList GetPropertiesIntoList(string fields) + { + IList properties = fields.ToLowerInvariant() + .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Trim()) + .Distinct() + .ToList(); + + return properties; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/MappingExtensions/AddressDtoMappings.cs b/MappingExtensions/AddressDtoMappings.cs similarity index 94% rename from Nop.Plugin.Api/MappingExtensions/AddressDtoMappings.cs rename to MappingExtensions/AddressDtoMappings.cs index de5ba90..992d972 100644 --- a/Nop.Plugin.Api/MappingExtensions/AddressDtoMappings.cs +++ b/MappingExtensions/AddressDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Common; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs; +using Nop.Plugin.Api.DTO; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/BaseMapping.cs b/MappingExtensions/BaseMapping.cs similarity index 100% rename from Nop.Plugin.Api/MappingExtensions/BaseMapping.cs rename to MappingExtensions/BaseMapping.cs diff --git a/Nop.Plugin.Api/MappingExtensions/CategoryDtoMappings.cs b/MappingExtensions/CategoryDtoMappings.cs similarity index 92% rename from Nop.Plugin.Api/MappingExtensions/CategoryDtoMappings.cs rename to MappingExtensions/CategoryDtoMappings.cs index 26abcf6..d85984c 100644 --- a/Nop.Plugin.Api/MappingExtensions/CategoryDtoMappings.cs +++ b/MappingExtensions/CategoryDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Categories; +using Nop.Plugin.Api.DTO.Categories; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ConfigurationMappings.cs b/MappingExtensions/ConfigurationMappings.cs similarity index 87% rename from Nop.Plugin.Api/MappingExtensions/ConfigurationMappings.cs rename to MappingExtensions/ConfigurationMappings.cs index bbac81b..ef464f8 100644 --- a/Nop.Plugin.Api/MappingExtensions/ConfigurationMappings.cs +++ b/MappingExtensions/ConfigurationMappings.cs @@ -1,4 +1,5 @@ -using Nop.Plugin.Api.AutoMapper; +using Nop.Plugin.Api.Areas.Admin.Models; +using Nop.Plugin.Api.AutoMapper; using Nop.Plugin.Api.Domain; using Nop.Plugin.Api.Models; diff --git a/Nop.Plugin.Api/MappingExtensions/CustomerDtoMappings.cs b/MappingExtensions/CustomerDtoMappings.cs similarity index 95% rename from Nop.Plugin.Api/MappingExtensions/CustomerDtoMappings.cs rename to MappingExtensions/CustomerDtoMappings.cs index ef1b37e..2b43cd6 100644 --- a/Nop.Plugin.Api/MappingExtensions/CustomerDtoMappings.cs +++ b/MappingExtensions/CustomerDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Plugin.Api.AutoMapper; using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.DTOs.Customers; +using Nop.Plugin.Api.DTO.Customers; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/CustomerRoleDtoMappings.cs b/MappingExtensions/CustomerRoleDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/CustomerRoleDtoMappings.cs rename to MappingExtensions/CustomerRoleDtoMappings.cs index 34bffc5..014f68f 100644 --- a/Nop.Plugin.Api/MappingExtensions/CustomerRoleDtoMappings.cs +++ b/MappingExtensions/CustomerRoleDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Plugin.Api.AutoMapper; using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.DTOs.CustomerRoles; +using Nop.Plugin.Api.DTO.CustomerRoles; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/LanguageDtoMappings.cs b/MappingExtensions/LanguageDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/LanguageDtoMappings.cs rename to MappingExtensions/LanguageDtoMappings.cs index 6f0000c..551e898 100644 --- a/Nop.Plugin.Api/MappingExtensions/LanguageDtoMappings.cs +++ b/MappingExtensions/LanguageDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Localization; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Languages; +using Nop.Plugin.Api.DTO.Languages; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ManufacturerDtoMappings.cs b/MappingExtensions/ManufacturerDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/ManufacturerDtoMappings.cs rename to MappingExtensions/ManufacturerDtoMappings.cs index 92eb2d7..b1ac5fe 100644 --- a/Nop.Plugin.Api/MappingExtensions/ManufacturerDtoMappings.cs +++ b/MappingExtensions/ManufacturerDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Manufacturers; +using Nop.Plugin.Api.DTO.Manufacturers; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs b/MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs similarity index 94% rename from Nop.Plugin.Api/MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs rename to MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs index f9fe51f..3310816 100644 --- a/Nop.Plugin.Api/MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs +++ b/MappingExtensions/NewsLetterSubscriptoonDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Messages; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Categories; +using Nop.Plugin.Api.DTO.Categories; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/OrderDtoMappings.cs b/MappingExtensions/OrderDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/OrderDtoMappings.cs rename to MappingExtensions/OrderDtoMappings.cs index 0d192b1..892985d 100644 --- a/Nop.Plugin.Api/MappingExtensions/OrderDtoMappings.cs +++ b/MappingExtensions/OrderDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Orders; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Orders; +using Nop.Plugin.Api.DTO.Orders; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/OrderItemDtoMappings.cs b/MappingExtensions/OrderItemDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/OrderItemDtoMappings.cs rename to MappingExtensions/OrderItemDtoMappings.cs index 3019d7c..69bbcc4 100644 --- a/Nop.Plugin.Api/MappingExtensions/OrderItemDtoMappings.cs +++ b/MappingExtensions/OrderItemDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Orders; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.OrderItems; +using Nop.Plugin.Api.DTO.OrderItems; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ProductAttributeCombinationDtoMappings.cs b/MappingExtensions/ProductAttributeCombinationDtoMappings.cs similarity index 92% rename from Nop.Plugin.Api/MappingExtensions/ProductAttributeCombinationDtoMappings.cs rename to MappingExtensions/ProductAttributeCombinationDtoMappings.cs index acc6e7d..2194447 100644 --- a/Nop.Plugin.Api/MappingExtensions/ProductAttributeCombinationDtoMappings.cs +++ b/MappingExtensions/ProductAttributeCombinationDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Products; +using Nop.Plugin.Api.DTO.Products; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ProductAttributeDtoMappings.cs b/MappingExtensions/ProductAttributeDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/ProductAttributeDtoMappings.cs rename to MappingExtensions/ProductAttributeDtoMappings.cs index ba003c0..570a954 100644 --- a/Nop.Plugin.Api/MappingExtensions/ProductAttributeDtoMappings.cs +++ b/MappingExtensions/ProductAttributeDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.ProductAttributes; +using Nop.Plugin.Api.DTO.ProductAttributes; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ProductCategoryMappingDtoMappings.cs b/MappingExtensions/ProductCategoryMappingDtoMappings.cs similarity index 87% rename from Nop.Plugin.Api/MappingExtensions/ProductCategoryMappingDtoMappings.cs rename to MappingExtensions/ProductCategoryMappingDtoMappings.cs index c1caf5d..fdf4ab3 100644 --- a/Nop.Plugin.Api/MappingExtensions/ProductCategoryMappingDtoMappings.cs +++ b/MappingExtensions/ProductCategoryMappingDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Plugin.Api.AutoMapper; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; +using Nop.Plugin.Api.DTO.ProductCategoryMappings; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ProductDtoMappings.cs b/MappingExtensions/ProductDtoMappings.cs similarity index 93% rename from Nop.Plugin.Api/MappingExtensions/ProductDtoMappings.cs rename to MappingExtensions/ProductDtoMappings.cs index ca43d3e..06160dd 100644 --- a/Nop.Plugin.Api/MappingExtensions/ProductDtoMappings.cs +++ b/MappingExtensions/ProductDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Plugin.Api.AutoMapper; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DTOs.Products; +using Nop.Plugin.Api.DTO.Products; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/ProductManufacturerMappingDtoMappings.cs b/MappingExtensions/ProductManufacturerMappingDtoMappings.cs similarity index 87% rename from Nop.Plugin.Api/MappingExtensions/ProductManufacturerMappingDtoMappings.cs rename to MappingExtensions/ProductManufacturerMappingDtoMappings.cs index 583858e..640141b 100644 --- a/Nop.Plugin.Api/MappingExtensions/ProductManufacturerMappingDtoMappings.cs +++ b/MappingExtensions/ProductManufacturerMappingDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.ProductManufacturerMappings; +using Nop.Plugin.Api.DTO.ProductManufacturerMappings; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/MappingExtensions/ShipmentDtoMappings.cs b/MappingExtensions/ShipmentDtoMappings.cs new file mode 100644 index 0000000..015765f --- /dev/null +++ b/MappingExtensions/ShipmentDtoMappings.cs @@ -0,0 +1,16 @@ +using Nop.Core.Domain.Shipping; +using Nop.Core.Domain.Stores; +using Nop.Plugin.Api.AutoMapper; +using Nop.Plugin.Api.DTO.Shipments; +using Nop.Plugin.Api.DTO.Stores; + +namespace Nop.Plugin.Api.MappingExtensions +{ + public static class ShipmentDtoMappings + { + public static ShipmentDto ToDto(this Shipment shipment) + { + return shipment.MapTo(); + } + } +} diff --git a/Nop.Plugin.Api/MappingExtensions/ShoppingCartItemDtoMappings.cs b/MappingExtensions/ShoppingCartItemDtoMappings.cs similarity index 90% rename from Nop.Plugin.Api/MappingExtensions/ShoppingCartItemDtoMappings.cs rename to MappingExtensions/ShoppingCartItemDtoMappings.cs index 7a31c07..bb921a2 100644 --- a/Nop.Plugin.Api/MappingExtensions/ShoppingCartItemDtoMappings.cs +++ b/MappingExtensions/ShoppingCartItemDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Plugin.Api.AutoMapper; using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DTOs.ShoppingCarts; +using Nop.Plugin.Api.DTO.ShoppingCarts; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/SpecificationAttributeDtoMapping.cs b/MappingExtensions/SpecificationAttributeDtoMapping.cs similarity index 94% rename from Nop.Plugin.Api/MappingExtensions/SpecificationAttributeDtoMapping.cs rename to MappingExtensions/SpecificationAttributeDtoMapping.cs index 5af3501..6b5161b 100644 --- a/Nop.Plugin.Api/MappingExtensions/SpecificationAttributeDtoMapping.cs +++ b/MappingExtensions/SpecificationAttributeDtoMapping.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Catalog; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.SpecificationAttributes; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/MappingExtensions/StoreDtoMappings.cs b/MappingExtensions/StoreDtoMappings.cs similarity index 89% rename from Nop.Plugin.Api/MappingExtensions/StoreDtoMappings.cs rename to MappingExtensions/StoreDtoMappings.cs index 230d738..ca1479f 100644 --- a/Nop.Plugin.Api/MappingExtensions/StoreDtoMappings.cs +++ b/MappingExtensions/StoreDtoMappings.cs @@ -1,6 +1,6 @@ using Nop.Core.Domain.Stores; using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.DTOs.Stores; +using Nop.Plugin.Api.DTO.Stores; namespace Nop.Plugin.Api.MappingExtensions { diff --git a/Nop.Plugin.Api/Maps/IJsonPropertyMap.cs b/Maps/IJsonPropertyMap.cs similarity index 100% rename from Nop.Plugin.Api/Maps/IJsonPropertyMap.cs rename to Maps/IJsonPropertyMap.cs diff --git a/Nop.Plugin.Api/Maps/JsonPropertyMap.cs b/Maps/JsonPropertyMap.cs similarity index 75% rename from Nop.Plugin.Api/Maps/JsonPropertyMap.cs rename to Maps/JsonPropertyMap.cs index c37a5ec..ccb1ea9 100644 --- a/Nop.Plugin.Api/Maps/JsonPropertyMap.cs +++ b/Maps/JsonPropertyMap.cs @@ -1,77 +1,77 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Newtonsoft.Json; -using Nop.Core.Caching; -using Nop.Core.Infrastructure; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Constants; - -namespace Nop.Plugin.Api.Maps -{ - public class JsonPropertyMapper : IJsonPropertyMapper - { - private IStaticCacheManager _cacheManager; - - private IStaticCacheManager StaticCacheManager - { - get - { - if (_cacheManager == null) - { - _cacheManager = EngineContext.Current.Resolve(); - } - - return _cacheManager; - } - } - - public Dictionary> GetMap(Type type) - { - if (!StaticCacheManager.IsSet(Configurations.JsonTypeMapsPattern)) - { - StaticCacheManager.Set(Configurations.JsonTypeMapsPattern, new Dictionary>>(), int.MaxValue); - } - - var typeMaps = StaticCacheManager.Get>>>(Configurations.JsonTypeMapsPattern, () => null, 0); - - if (!typeMaps.ContainsKey(type.Name)) - { - Build(type); - } - - return typeMaps[type.Name]; - } - - private void Build(Type type) - { - var typeMaps = - StaticCacheManager.Get>>>(Configurations.JsonTypeMapsPattern, () => null, 0); - - var mapForCurrentType = new Dictionary>(); - - var typeProps = type.GetProperties(); - - foreach (var property in typeProps) - { - var jsonAttribute = property.GetCustomAttribute(typeof(JsonPropertyAttribute)) as JsonPropertyAttribute; - var doNotMapAttribute = property.GetCustomAttribute(typeof(DoNotMapAttribute)) as DoNotMapAttribute; - - // If it has json attribute set and is not marked as doNotMap - if (jsonAttribute != null && doNotMapAttribute == null) - { - if (!mapForCurrentType.ContainsKey(jsonAttribute.PropertyName)) - { - var value = new Tuple(property.Name, property.PropertyType); - mapForCurrentType.Add(jsonAttribute.PropertyName, value); - } - } - } - - if (!typeMaps.ContainsKey(type.Name)) - { - typeMaps.Add(type.Name, mapForCurrentType); - } - } - } +using System; +using System.Collections.Generic; +using System.Reflection; +using Newtonsoft.Json; +using Nop.Core.Caching; +using Nop.Core.Infrastructure; +using Nop.Plugin.Api.Attributes; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Maps +{ + public class JsonPropertyMapper : IJsonPropertyMapper + { + private IStaticCacheManager _cacheManager; + + private IStaticCacheManager StaticCacheManager + { + get + { + if (_cacheManager == null) + { + _cacheManager = EngineContext.Current.Resolve(); + } + + return _cacheManager; + } + } + + public Dictionary> GetMap(Type type) + { + //if (!StaticCacheManager.IsSet(Configurations.JsonTypeMapsPattern)) + //{ + // StaticCacheManager.Set(Configurations.JsonTypeMapsPattern, new Dictionary>>(), int.MaxValue); + //} + + var typeMaps = StaticCacheManager.Get(Configurations.JsonTypeMapsPattern, () => new Dictionary>>()); + + if (!typeMaps.ContainsKey(type.Name)) + { + Build(type); + } + + return typeMaps[type.Name]; + } + + private void Build(Type type) + { + var typeMaps = + StaticCacheManager.Get(Configurations.JsonTypeMapsPattern, () => new Dictionary>>()); + + var mapForCurrentType = new Dictionary>(); + + var typeProps = type.GetProperties(); + + foreach (var property in typeProps) + { + var jsonAttribute = property.GetCustomAttribute(typeof(JsonPropertyAttribute)) as JsonPropertyAttribute; + var doNotMapAttribute = property.GetCustomAttribute(typeof(DoNotMapAttribute)) as DoNotMapAttribute; + + // If it has json attribute set and is not marked as doNotMap + if (jsonAttribute != null && doNotMapAttribute == null) + { + if (!mapForCurrentType.ContainsKey(jsonAttribute.PropertyName)) + { + var value = new Tuple(property.Name, property.PropertyType); + mapForCurrentType.Add(jsonAttribute.PropertyName, value); + } + } + } + + if (!typeMaps.ContainsKey(type.Name)) + { + typeMaps.Add(type.Name, mapForCurrentType); + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/ModelBinders/JsonModelBinder.cs b/ModelBinders/JsonModelBinder.cs similarity index 87% rename from Nop.Plugin.Api/ModelBinders/JsonModelBinder.cs rename to ModelBinders/JsonModelBinder.cs index 7b60a8e..4df6a33 100644 --- a/Nop.Plugin.Api/ModelBinders/JsonModelBinder.cs +++ b/ModelBinders/JsonModelBinder.cs @@ -1,203 +1,215 @@ -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.Delta; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.Validators; -using Nop.Services.Localization; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; - -namespace Nop.Plugin.Api.ModelBinders -{ - using Microsoft.AspNetCore.Mvc; - using Microsoft.AspNetCore.Mvc.ModelBinding; - using System; - - public class JsonModelBinder : IModelBinder where T : class, new() - { - private readonly IJsonHelper _jsonHelper; - private readonly ILocalizationService _localizationService; - - private readonly int _languageId; - - public JsonModelBinder(IJsonHelper jsonHelper, ILocalizationService localizationService, ILanguageService languageService) - { - _jsonHelper = jsonHelper; - _localizationService = localizationService; - - // Languages are ordered by display order so the first language will be with the smallest display order. - var firstLanguage = languageService.GetAllLanguages().FirstOrDefault(); - if (firstLanguage != null) - { - _languageId = firstLanguage.Id; - } - else - { - _languageId = 0; - } - } - - public Task BindModelAsync(ModelBindingContext bindingContext) - { - var propertyValuePairs = GetPropertyValuePairs(bindingContext); - if (propertyValuePairs == null) - { - bindingContext.Result = ModelBindingResult.Failed(); - return Task.CompletedTask; - } - - if (bindingContext.ModelState.IsValid) - { - // You will have id parameter passed in the model binder only when you have put request. - // because get and delete do not use the model binder. - // Here we insert the id in the property value pairs to be validated by the dto validator in a later point. - var routeDataId = GetRouteDataId(bindingContext.ActionContext); - - if (routeDataId != null) - { - // Here we insert the route data id in the value paires. - // If id is contained in the category json body the one from the route data is used instead. - InsertIdInTheValuePaires(propertyValuePairs, routeDataId); - } - - // We need to call this method here so it will be certain that the routeDataId will be in the propertyValuePaires - // when the request is PUT. - ValidateValueTypes(bindingContext, propertyValuePairs); - - Delta delta = null; - - if (bindingContext.ModelState.IsValid) - { - delta = new Delta(propertyValuePairs); - ValidateModel(bindingContext, propertyValuePairs, delta.Dto); - } - - if (bindingContext.ModelState.IsValid) - { - bindingContext.Model = delta; - bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); - } - else - { - bindingContext.Result = ModelBindingResult.Failed(); - } - } - else - { - bindingContext.Result = ModelBindingResult.Failed(); - } - - return Task.CompletedTask; - } - - private Dictionary GetPropertyValuePairs(ModelBindingContext bindingContext) - { - Dictionary result = null; - - if (bindingContext.ModelState.IsValid) - { - try - { - //get the root dictionary and root property (these will throw exceptions if they fail) - result = _jsonHelper.GetRequestJsonDictionaryFromStream(bindingContext.HttpContext.Request.Body, true); - var rootPropertyName = _jsonHelper.GetRootPropertyName(); - - result = (Dictionary)result[rootPropertyName]; - } - catch (Exception ex) - { - bindingContext.ModelState.AddModelError("json", ex.Message); - } - } - - return result; - } - - private object GetRouteDataId(ActionContext actionContext) - { - object routeDataId = null; - - if (actionContext.RouteData.Values.ContainsKey("id")) - { - routeDataId = actionContext.RouteData.Values["id"]; - } - - return routeDataId; - } - - private void ValidateValueTypes(ModelBindingContext bindingContext, Dictionary propertyValuePaires) - { - var errors = new Dictionary(); - - // Validate if the property value pairs passed maches the type. - var typeValidator = new TypeValidator(); - - if (!typeValidator.IsValid(propertyValuePaires)) - { - foreach (var invalidProperty in typeValidator.InvalidProperties) - { - var key = string.Format(_localizationService.GetResource("Api.InvalidType", _languageId, false), invalidProperty); - - if (!errors.ContainsKey(key)) - { - errors.Add(key, _localizationService.GetResource("Api.InvalidPropertyType", _languageId, false)); - } - } - } - - if (errors.Count > 0) - { - foreach (var error in errors) - { - bindingContext.ModelState.AddModelError(error.Key, error.Value); - } - } - } - - private void ValidateModel(ModelBindingContext bindingContext, Dictionary propertyValuePaires, T dto) - { - // this method validates each property by checking if it has an attribute that inherits from BaseValidationAttribute - // these attribtues are different than FluentValidation attributes, so they need to be validated manually - - var dtoProperties = dto.GetType().GetProperties(); - foreach (var property in dtoProperties) - { - // Check property type - var validationAttribute = property.PropertyType.GetCustomAttribute(typeof(BaseValidationAttribute)) as BaseValidationAttribute; - - // If not on property type, check the property itself. - if (validationAttribute == null) - { - validationAttribute = property.GetCustomAttribute(typeof(BaseValidationAttribute)) as BaseValidationAttribute; - } - - if (validationAttribute != null) - { - validationAttribute.Validate(property.GetValue(dto)); - var errors = validationAttribute.GetErrors(); - - if (errors.Count > 0) - { - foreach (var error in errors) - { - bindingContext.ModelState.AddModelError(error.Key, error.Value); - } - } - } - } - } - - private void InsertIdInTheValuePaires(Dictionary propertyValuePaires, object requestId) - { - if (propertyValuePaires.ContainsKey("id")) - { - propertyValuePaires["id"] = requestId; - } - else - { - propertyValuePaires.Add("id", requestId); - } - } - } +using Nop.Plugin.Api.Attributes; +using Nop.Plugin.Api.Delta; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.Validators; +using Nop.Services.Localization; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace Nop.Plugin.Api.ModelBinders +{ + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.ModelBinding; + using System; + + public class JsonModelBinder : IModelBinder where T : class, new() + { + private readonly IJsonHelper _jsonHelper; + private readonly ILocalizationService _localizationService; + + private readonly int _languageId; + + public JsonModelBinder(IJsonHelper jsonHelper, ILocalizationService localizationService, ILanguageService languageService) + { + _jsonHelper = jsonHelper; + _localizationService = localizationService; + + // Languages are ordered by display order so the first language will be with the smallest display order. + var firstLanguage = languageService.GetAllLanguages().FirstOrDefault(); + if (firstLanguage != null) + { + _languageId = firstLanguage.Id; + } + else + { + _languageId = 0; + } + } + + public Task BindModelAsync(ModelBindingContext bindingContext) + { + var propertyValuePairs = GetPropertyValuePairs(bindingContext); + if (propertyValuePairs == null) + { + bindingContext.Result = ModelBindingResult.Failed(); + return Task.CompletedTask; + } + + if (bindingContext.ModelState.IsValid) + { + // You will have id parameter passed in the model binder only when you have put request. + // because get and delete do not use the model binder. + // Here we insert the id in the property value pairs to be validated by the dto validator in a later point. + var routeDataId = GetRouteDataId(bindingContext.ActionContext); + + if (routeDataId != null) + { + // Here we insert the route data id in the value paires. + // If id is contained in the category json body the one from the route data is used instead. + InsertIdInTheValuePaires(propertyValuePairs, routeDataId); + } + + // We need to call this method here so it will be certain that the routeDataId will be in the propertyValuePaires + // when the request is PUT. + ValidateValueTypes(bindingContext, propertyValuePairs); + + Delta delta = null; + + if (bindingContext.ModelState.IsValid) + { + delta = new Delta(propertyValuePairs); + ValidateModel(bindingContext, propertyValuePairs, delta.Dto); + } + + if (bindingContext.ModelState.IsValid) + { + bindingContext.Model = delta; + bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); + } + else + { + bindingContext.Result = ModelBindingResult.Failed(); + } + } + else + { + bindingContext.Result = ModelBindingResult.Failed(); + } + + return Task.CompletedTask; + } + + private Dictionary GetPropertyValuePairs(ModelBindingContext bindingContext) + { + Dictionary result = null; + + if (bindingContext.ModelState.IsValid) + { + try + { + //get the root dictionary and root property (these will throw exceptions if they fail) + result = _jsonHelper.GetRequestJsonDictionaryFromStream(bindingContext.HttpContext.Request.Body, true); + var rootPropertyName = _jsonHelper.GetRootPropertyName(); + + result = (Dictionary)result[rootPropertyName]; + } + catch (Exception ex) + { + bindingContext.ModelState.AddModelError("json", ex.Message); + } + } + + return result; + } + + private object GetRouteDataId(ActionContext actionContext) + { + object routeDataId = null; + + if (actionContext.RouteData.Values.ContainsKey("id")) + { + routeDataId = actionContext.RouteData.Values["id"]; + } + + return routeDataId; + } + + private void ValidateValueTypes(ModelBindingContext bindingContext, Dictionary propertyValuePaires) + { + var errors = new Dictionary(); + + // Validate if the property value pairs passed maches the type. + var typeValidator = new TypeValidator(); + + if (!typeValidator.IsValid(propertyValuePaires)) + { + foreach (var invalidProperty in typeValidator.InvalidProperties) + { + var key = string.Format(_localizationService.GetResource("Api.InvalidType", _languageId, false), invalidProperty); + + if (!errors.ContainsKey(key)) + { + errors.Add(key, _localizationService.GetResource("Api.InvalidPropertyType", _languageId, false)); + } + } + } + + if (errors.Count > 0) + { + foreach (var error in errors) + { + bindingContext.ModelState.AddModelError(error.Key, error.Value); + } + } + } + + private void ValidateModel(ModelBindingContext bindingContext, Dictionary propertyValuePaires, T dto) + { + // this method validates each property by checking if it has an attribute that inherits from BaseValidationAttribute + // these attribtues are different than FluentValidation attributes, so they need to be validated manually + // this method also validates the class level attributes + + var dtoType = dto.GetType(); + + var classValidationAttribute = dtoType.GetCustomAttribute(typeof(BaseValidationAttribute)) as BaseValidationAttribute; + if (classValidationAttribute != null) + ValidateAttribute(bindingContext, classValidationAttribute, dto); + + var dtoProperties = dtoType.GetProperties(); + foreach (var property in dtoProperties) + { + // Check property type + var validationAttribute = property.PropertyType.GetCustomAttribute(typeof(BaseValidationAttribute)) as BaseValidationAttribute; + + // If not on property type, check the property itself. + if (validationAttribute == null) + { + validationAttribute = property.GetCustomAttribute(typeof(BaseValidationAttribute)) as BaseValidationAttribute; + } + + if (validationAttribute != null) + { + ValidateAttribute(bindingContext, validationAttribute, property.GetValue(dto)); + } + } + } + + private void ValidateAttribute(ModelBindingContext bindingContext, BaseValidationAttribute validator, object value) + { + validator.Validate(value); + var errors = validator.GetErrors(); + + if (errors.Count > 0) + { + foreach (var error in errors) + { + bindingContext.ModelState.AddModelError(error.Key, error.Value); + } + } + } + + private void InsertIdInTheValuePaires(Dictionary propertyValuePaires, object requestId) + { + if (propertyValuePaires.ContainsKey("id")) + { + propertyValuePaires["id"] = requestId; + } + else + { + propertyValuePaires.Add("id", requestId); + } + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/ModelBinders/ParametersModelBinder.cs b/ModelBinders/ParametersModelBinder.cs similarity index 97% rename from Nop.Plugin.Api/ModelBinders/ParametersModelBinder.cs rename to ModelBinders/ParametersModelBinder.cs index 1787e44..da18a4c 100644 --- a/Nop.Plugin.Api/ModelBinders/ParametersModelBinder.cs +++ b/ModelBinders/ParametersModelBinder.cs @@ -1,43 +1,43 @@ -using Nop.Plugin.Api.Converters; - -namespace Nop.Plugin.Api.ModelBinders -{ - using System; - using System.Linq; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Mvc.ModelBinding; - - public class ParametersModelBinder : IModelBinder where T : class, new() - { - private readonly IObjectConverter _objectConverter; - - public ParametersModelBinder(IObjectConverter objectConverter) - { - _objectConverter = objectConverter; - } - - public Task BindModelAsync(ModelBindingContext bindingContext) - { - if (bindingContext == null) - { - throw new ArgumentNullException(nameof(bindingContext)); - } - - if (bindingContext.HttpContext.Request.QueryString.HasValue) - { - var queryParameters = bindingContext.HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => pair.Value.ToString()); - - bindingContext.Model = _objectConverter.ToObject(queryParameters); - } - else - { - bindingContext.Model = new T(); - } - - bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); - - // This should be true otherwise the model will be null. - return Task.CompletedTask; - } - } +using Nop.Plugin.Api.Converters; + +namespace Nop.Plugin.Api.ModelBinders +{ + using System; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc.ModelBinding; + + public class ParametersModelBinder : IModelBinder where T : class, new() + { + private readonly IObjectConverter _objectConverter; + + public ParametersModelBinder(IObjectConverter objectConverter) + { + _objectConverter = objectConverter; + } + + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if (bindingContext == null) + { + throw new ArgumentNullException(nameof(bindingContext)); + } + + if (bindingContext.HttpContext.Request.QueryString.HasValue) + { + var queryParameters = bindingContext.HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => pair.Value.ToString()); + + bindingContext.Model = _objectConverter.ToObject(queryParameters); + } + else + { + bindingContext.Model = new T(); + } + + bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); + + // This should be true otherwise the model will be null. + return Task.CompletedTask; + } + } } \ No newline at end of file diff --git a/Models/Authentication/TokenRequest.cs b/Models/Authentication/TokenRequest.cs new file mode 100644 index 0000000..d31ac17 --- /dev/null +++ b/Models/Authentication/TokenRequest.cs @@ -0,0 +1,9 @@ +namespace Nop.Plugin.Api.Models.Authentication +{ + public class TokenRequest + { + public string Username { get; set; } + + public string Password { get; set; } + } +} diff --git a/Models/Authentication/TokenResponse.cs b/Models/Authentication/TokenResponse.cs new file mode 100644 index 0000000..25915fb --- /dev/null +++ b/Models/Authentication/TokenResponse.cs @@ -0,0 +1,31 @@ +using Newtonsoft.Json; + +namespace Nop.Plugin.Api.Models.Authentication +{ + public class TokenResponse + { + public TokenResponse(string errorDescription) + { + ErrorDescription = errorDescription; + } + + public TokenResponse(string accessToken, long expiresInSeconds, string tokenType = "Bearer") + { + AccessToken = accessToken; + ExpiresInSeconds = expiresInSeconds; + TokenType = tokenType; + } + + [JsonProperty("access_token")] + public string AccessToken { get; set; } + + [JsonProperty("token_type")] + public string TokenType { get; set; } = "Bearer"; + + [JsonProperty("expires_in")] + public long ExpiresInSeconds { get; set; } + + [JsonProperty("error_description")] + public string ErrorDescription { get; set; } + } +} diff --git a/Nop.Plugin.Api/Models/CategoriesParameters/BaseCategoriesParametersModel.cs b/Models/CategoriesParameters/BaseCategoriesParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/CategoriesParameters/BaseCategoriesParametersModel.cs rename to Models/CategoriesParameters/BaseCategoriesParametersModel.cs diff --git a/Nop.Plugin.Api/Models/CategoriesParameters/CategoriesCountParametersModel.cs b/Models/CategoriesParameters/CategoriesCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/CategoriesParameters/CategoriesCountParametersModel.cs rename to Models/CategoriesParameters/CategoriesCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/CategoriesParameters/CategoriesParametersModel.cs b/Models/CategoriesParameters/CategoriesParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/CategoriesParameters/CategoriesParametersModel.cs rename to Models/CategoriesParameters/CategoriesParametersModel.cs index 53b60cb..3d3389d 100644 --- a/Nop.Plugin.Api/Models/CategoriesParameters/CategoriesParametersModel.cs +++ b/Models/CategoriesParameters/CategoriesParametersModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; using Microsoft.AspNetCore.Mvc; diff --git a/Nop.Plugin.Api/Models/ClientApiModel.cs b/Models/ClientApiModel.cs similarity index 66% rename from Nop.Plugin.Api/Models/ClientApiModel.cs rename to Models/ClientApiModel.cs index 243c0c8..978310b 100644 --- a/Nop.Plugin.Api/Models/ClientApiModel.cs +++ b/Models/ClientApiModel.cs @@ -1,8 +1,10 @@ -namespace Nop.Plugin.Api.Models +using Nop.Web.Framework.Models; + +namespace Nop.Plugin.Api.Models { - public class ClientApiModel + public class ClientApiModel : BaseNopModel { - + public int Id { get; set; } public string ClientName { get; set; } @@ -22,14 +24,20 @@ public string ClientSecret public int AccessTokenLifetime { - get;set; + get; set; } public int RefreshTokenLifetime { - get;set; + get; set; } public bool Enabled { get; set; } } + + public class ClientApiListModel : BasePagedListModel + { + + } + } \ No newline at end of file diff --git a/Models/ClientApiSearchModel.cs b/Models/ClientApiSearchModel.cs new file mode 100644 index 0000000..5c73ff9 --- /dev/null +++ b/Models/ClientApiSearchModel.cs @@ -0,0 +1,11 @@ +using Nop.Web.Framework.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Nop.Plugin.Api.Models +{ + public class ClientApiSearchModel : BaseSearchModel + { + } +} diff --git a/Nop.Plugin.Api/Models/CustomersParameters/CustomersParametersModel.cs b/Models/CustomersParameters/CustomersParametersModel.cs similarity index 97% rename from Nop.Plugin.Api/Models/CustomersParameters/CustomersParametersModel.cs rename to Models/CustomersParameters/CustomersParametersModel.cs index b131ce5..cc41a65 100644 --- a/Nop.Plugin.Api/Models/CustomersParameters/CustomersParametersModel.cs +++ b/Models/CustomersParameters/CustomersParametersModel.cs @@ -1,6 +1,6 @@ using System; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.CustomersParameters diff --git a/Nop.Plugin.Api/Models/CustomersParameters/CustomersSearchParametersModel.cs b/Models/CustomersParameters/CustomersSearchParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/CustomersParameters/CustomersSearchParametersModel.cs rename to Models/CustomersParameters/CustomersSearchParametersModel.cs index 77fcc3d..8d43515 100644 --- a/Nop.Plugin.Api/Models/CustomersParameters/CustomersSearchParametersModel.cs +++ b/Models/CustomersParameters/CustomersSearchParametersModel.cs @@ -1,5 +1,5 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.CustomersParameters diff --git a/Nop.Plugin.Api/Models/DefaultWeApiErrorsModel.cs b/Models/DefaultWeApiErrorsModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/DefaultWeApiErrorsModel.cs rename to Models/DefaultWeApiErrorsModel.cs diff --git a/Nop.Plugin.Api/Models/ManufacturersParameters/BaseManufacturersParametersModel.cs b/Models/ManufacturersParameters/BaseManufacturersParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ManufacturersParameters/BaseManufacturersParametersModel.cs rename to Models/ManufacturersParameters/BaseManufacturersParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ManufacturersParameters/ManufacturersCountParametersModel.cs b/Models/ManufacturersParameters/ManufacturersCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ManufacturersParameters/ManufacturersCountParametersModel.cs rename to Models/ManufacturersParameters/ManufacturersCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ManufacturersParameters/ManufacturersParametersModel.cs b/Models/ManufacturersParameters/ManufacturersParametersModel.cs similarity index 97% rename from Nop.Plugin.Api/Models/ManufacturersParameters/ManufacturersParametersModel.cs rename to Models/ManufacturersParameters/ManufacturersParametersModel.cs index c4ffa56..f1ccb68 100644 --- a/Nop.Plugin.Api/Models/ManufacturersParameters/ManufacturersParametersModel.cs +++ b/Models/ManufacturersParameters/ManufacturersParametersModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; using Microsoft.AspNetCore.Mvc; diff --git a/Nop.Plugin.Api/Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs b/Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs similarity index 97% rename from Nop.Plugin.Api/Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs rename to Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs index a62b9e7..e21d2a6 100644 --- a/Nop.Plugin.Api/Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs +++ b/Models/NewsLetterSubscriptionsParameters/NewsLetterSubscriptionsParametersModel.cs @@ -1,6 +1,6 @@ using System; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.CustomersParameters diff --git a/Nop.Plugin.Api/Models/OrderItemsParameters/OrderItemsParametersModel.cs b/Models/OrderItemsParameters/OrderItemsParametersModel.cs similarity index 93% rename from Nop.Plugin.Api/Models/OrderItemsParameters/OrderItemsParametersModel.cs rename to Models/OrderItemsParameters/OrderItemsParametersModel.cs index 6d79a81..f122a5d 100644 --- a/Nop.Plugin.Api/Models/OrderItemsParameters/OrderItemsParametersModel.cs +++ b/Models/OrderItemsParameters/OrderItemsParametersModel.cs @@ -1,5 +1,5 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.OrderItemsParameters diff --git a/Nop.Plugin.Api/Models/OrdersParameters/BaseOrdersParametersModel.cs b/Models/OrdersParameters/BaseOrdersParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/OrdersParameters/BaseOrdersParametersModel.cs rename to Models/OrdersParameters/BaseOrdersParametersModel.cs diff --git a/Models/OrdersParameters/OrdersCountParametersModel.cs b/Models/OrdersParameters/OrdersCountParametersModel.cs new file mode 100644 index 0000000..d71091b --- /dev/null +++ b/Models/OrdersParameters/OrdersCountParametersModel.cs @@ -0,0 +1,23 @@ +using Nop.Plugin.Api.ModelBinders; + +namespace Nop.Plugin.Api.Models.OrdersParameters +{ + using Microsoft.AspNetCore.Mvc; + using Newtonsoft.Json; + using static Nop.Plugin.Api.Infrastructure.Constants; + + [ModelBinder(typeof(ParametersModelBinder))] + public class OrdersCountParametersModel : BaseOrdersParametersModel + { + public OrdersCountParametersModel() + { + SinceId = Configurations.DefaultSinceId; + } + + /// + /// Restrict results to after the specified ID + /// + [JsonProperty("since_id")] + public int SinceId { get; set; } + } +} \ No newline at end of file diff --git a/Nop.Plugin.Api/Models/OrdersParameters/OrdersParametersModel.cs b/Models/OrdersParameters/OrdersParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/OrdersParameters/OrdersParametersModel.cs rename to Models/OrdersParameters/OrdersParametersModel.cs index b02c1e0..75f5414 100644 --- a/Nop.Plugin.Api/Models/OrdersParameters/OrdersParametersModel.cs +++ b/Models/OrdersParameters/OrdersParametersModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.OrdersParameters diff --git a/Nop.Plugin.Api/Models/ProductAttributesParameters/ProductAttributesParametersModel.cs b/Models/ProductAttributesParameters/ProductAttributesParametersModel.cs similarity index 94% rename from Nop.Plugin.Api/Models/ProductAttributesParameters/ProductAttributesParametersModel.cs rename to Models/ProductAttributesParameters/ProductAttributesParametersModel.cs index 690dcbc..488300a 100644 --- a/Nop.Plugin.Api/Models/ProductAttributesParameters/ProductAttributesParametersModel.cs +++ b/Models/ProductAttributesParameters/ProductAttributesParametersModel.cs @@ -1,52 +1,52 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.ModelBinders; - -namespace Nop.Plugin.Api.Models.ProductAttributes -{ - // JsonProperty is used only for swagger - [ModelBinder(typeof(ParametersModelBinder))] - public class ProductAttributesParametersModel - { - public ProductAttributesParametersModel() - { - Ids = null; - Limit = Configurations.DefaultLimit; - Page = Configurations.DefaultPageValue; - SinceId = Configurations.DefaultSinceId; - Fields = string.Empty; - } - - /// - /// A comma-separated list of category ids - /// - [JsonProperty("ids")] - public List Ids { get; set; } - - /// - /// Amount of results (default: 50) (maximum: 250) - /// - [JsonProperty("limit")] - public int Limit { get; set; } - - /// - /// Page to show (default: 1) - /// - [JsonProperty("page")] - public int Page { get; set; } - - /// - /// Restrict results to after the specified ID - /// - [JsonProperty("since_id")] - public int SinceId { get; set; } - - /// - /// comma-separated list of fields to include in the response - /// - [JsonProperty("fields")] - public string Fields { get; set; } - } +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using static Nop.Plugin.Api.Infrastructure.Constants; +using Nop.Plugin.Api.ModelBinders; + +namespace Nop.Plugin.Api.Models.ProductAttributes +{ + // JsonProperty is used only for swagger + [ModelBinder(typeof(ParametersModelBinder))] + public class ProductAttributesParametersModel + { + public ProductAttributesParametersModel() + { + Ids = null; + Limit = Configurations.DefaultLimit; + Page = Configurations.DefaultPageValue; + SinceId = Configurations.DefaultSinceId; + Fields = string.Empty; + } + + /// + /// A comma-separated list of category ids + /// + [JsonProperty("ids")] + public List Ids { get; set; } + + /// + /// Amount of results (default: 50) (maximum: 250) + /// + [JsonProperty("limit")] + public int Limit { get; set; } + + /// + /// Page to show (default: 1) + /// + [JsonProperty("page")] + public int Page { get; set; } + + /// + /// Restrict results to after the specified ID + /// + [JsonProperty("since_id")] + public int SinceId { get; set; } + + /// + /// comma-separated list of fields to include in the response + /// + [JsonProperty("fields")] + public string Fields { get; set; } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/BaseCategoryMappingsParametersModel.cs b/Models/ProductCategoryMappingsParameters/BaseCategoryMappingsParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/BaseCategoryMappingsParametersModel.cs rename to Models/ProductCategoryMappingsParameters/BaseCategoryMappingsParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsCountParametersModel.cs b/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsCountParametersModel.cs rename to Models/ProductCategoryMappingsParameters/ProductCategoryMappingsCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs b/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs rename to Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs index b5e84bb..8ce792e 100644 --- a/Nop.Plugin.Api/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs +++ b/Models/ProductCategoryMappingsParameters/ProductCategoryMappingsParametersModel.cs @@ -1,5 +1,5 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.ProductCategoryMappingsParameters diff --git a/Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/BaseManufacturerMappingsParametersModel.cs b/Models/ProductManufacturerMappingsParameters/BaseManufacturerMappingsParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/BaseManufacturerMappingsParametersModel.cs rename to Models/ProductManufacturerMappingsParameters/BaseManufacturerMappingsParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsCountParametersModel.cs b/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsCountParametersModel.cs rename to Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs b/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs rename to Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs index afc08e6..72bf387 100644 --- a/Nop.Plugin.Api/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs +++ b/Models/ProductManufacturerMappingsParameters/ProductManufacturerMappingsParametersModel.cs @@ -1,5 +1,5 @@ using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.ProductManufacturerMappingsParameters diff --git a/Nop.Plugin.Api/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesCountParametersModel.cs b/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesCountParametersModel.cs rename to Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs b/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs similarity index 97% rename from Nop.Plugin.Api/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs rename to Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs index 7e86751..63ad43c 100644 --- a/Nop.Plugin.Api/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs +++ b/Models/ProductSpecificationAttributesParameters/ProductSpecificationAttributesParametersModel.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.ProductSpecificationAttributes diff --git a/Nop.Plugin.Api/Models/ProductsParameters/BaseProductsParametersModel.cs b/Models/ProductsParameters/BaseProductsParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductsParameters/BaseProductsParametersModel.cs rename to Models/ProductsParameters/BaseProductsParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductsParameters/ProductsCountParametersModel.cs b/Models/ProductsParameters/ProductsCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ProductsParameters/ProductsCountParametersModel.cs rename to Models/ProductsParameters/ProductsCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ProductsParameters/ProductsParametersModel.cs b/Models/ProductsParameters/ProductsParametersModel.cs similarity index 96% rename from Nop.Plugin.Api/Models/ProductsParameters/ProductsParametersModel.cs rename to Models/ProductsParameters/ProductsParametersModel.cs index 081580f..6c8f052 100644 --- a/Nop.Plugin.Api/Models/ProductsParameters/ProductsParametersModel.cs +++ b/Models/ProductsParameters/ProductsParametersModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.ProductsParameters diff --git a/Nop.Plugin.Api/Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs b/Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs similarity index 97% rename from Nop.Plugin.Api/Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs rename to Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs index 97ab0b9..5cf2fa7 100644 --- a/Nop.Plugin.Api/Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs +++ b/Models/ShoppingCartsParameters/BaseShoppingCartItemsParametersModel.cs @@ -1,6 +1,6 @@ using System; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Models.ShoppingCartsParameters { diff --git a/Nop.Plugin.Api/Models/ShoppingCartsParameters/ShoppingCartItemsForCustomerParametersModel.cs b/Models/ShoppingCartsParameters/ShoppingCartItemsForCustomerParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ShoppingCartsParameters/ShoppingCartItemsForCustomerParametersModel.cs rename to Models/ShoppingCartsParameters/ShoppingCartItemsForCustomerParametersModel.cs diff --git a/Nop.Plugin.Api/Models/ShoppingCartsParameters/ShoppingCartItemsParametersModel.cs b/Models/ShoppingCartsParameters/ShoppingCartItemsParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/ShoppingCartsParameters/ShoppingCartItemsParametersModel.cs rename to Models/ShoppingCartsParameters/ShoppingCartItemsParametersModel.cs diff --git a/Nop.Plugin.Api/Models/SpecificationAttributesParameters/SpecificationAttributesCountParametersModel.cs b/Models/SpecificationAttributesParameters/SpecificationAttributesCountParametersModel.cs similarity index 100% rename from Nop.Plugin.Api/Models/SpecificationAttributesParameters/SpecificationAttributesCountParametersModel.cs rename to Models/SpecificationAttributesParameters/SpecificationAttributesCountParametersModel.cs diff --git a/Nop.Plugin.Api/Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs b/Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs similarity index 95% rename from Nop.Plugin.Api/Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs rename to Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs index 419dbff..3dd0b89 100644 --- a/Nop.Plugin.Api/Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs +++ b/Models/SpecificationAttributesParameters/SpecificationAttributesParametersModel.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using Nop.Plugin.Api.ModelBinders; namespace Nop.Plugin.Api.Models.SpecificationAttributes diff --git a/Models/TaxCategory/TaxCategoriesParametersModel.cs b/Models/TaxCategory/TaxCategoriesParametersModel.cs new file mode 100644 index 0000000..ec2de17 --- /dev/null +++ b/Models/TaxCategory/TaxCategoriesParametersModel.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using static Nop.Plugin.Api.Infrastructure.Constants; +using Nop.Plugin.Api.ModelBinders; + +namespace Nop.Plugin.Api.Models.ProductsParameters +{ + using Microsoft.AspNetCore.Mvc; + + // JsonProperty is used only for swagger + [ModelBinder(typeof(ParametersModelBinder))] + public class TaxCategoriesParametersModel : BaseProductsParametersModel + { + } +} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_CreateCategory.cs b/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_CreateCategory.cs deleted file mode 100644 index 3c51c7a..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_CreateCategory.cs +++ /dev/null @@ -1,61 +0,0 @@ -//using System.Collections.Generic; -//using AutoMock; -//using Nop.Plugin.Api.Controllers; -//using NUnit.Framework; - -//namespace Nop.Plugin.Api.Tests.ControllersTests.Categories -//{ -// using Microsoft.AspNetCore.Mvc; - -// [TestFixture] -// public class CategoriesControllerTests_CreateCategory -// { -// [Test] -// public void WhenCategoryRootParameterIsNull_ShouldReturnBadRequest() -// { -// // Arrange -// var autoMocker = new RhinoAutoMocker(); - -// // Act -// IActionResult result = autoMocker.ClassUnderTest.CreateCategory(null); - -// // Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// public void WhenCategoryRootParameterIsEmpty_ShouldReturnBadRequest() -// { -// // Arrange -// var autoMocker = new RhinoAutoMocker(); - -// // Act -// IActionResult result = autoMocker.ClassUnderTest.CreateCategory(new Dictionary()); - -// // Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// public void WhenCategoryRootParameterDoesNotContainCategoryObjectOnRootLevel_ShouldReturnBadRequest() -// { -// // Arrange -// var autoMocker = new RhinoAutoMocker(); - -// // Act -// IActionResult result = autoMocker.ClassUnderTest.CreateCategory(new Dictionary() -// { -// { -// "this should be category", -// "collection of property-values" -// } -// }); - -// // Assert -// Assert.IsInstanceOf(result); -// } - -// // could not test anything with valid object because of the static extension methods that we are required to use when creating a new category -// // and the limitation of Rhino Mocks. -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategories.cs b/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategories.cs deleted file mode 100644 index 65a1795..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategories.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.Models.CategoriesParameters; -using Nop.Plugin.Api.Services; -using Nop.Services.Stores; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Categories -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class CategoriesControllerTests_GetCategories - { - private RhinoAutoMocker _authMocker; - - [SetUp] - public void Setup() - { - _authMocker = new RhinoAutoMocker(); - - _authMocker.Get().Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _authMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - } - - [Test] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parameters = new CategoriesParametersModel() - { - Limit = invalidLimit - }; - - //Arange - _authMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = _authMocker.ClassUnderTest.GetCategories(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) - { - var parameters = new CategoriesParametersModel() - { - Page = invalidPage - }; - - //Arange - _authMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = _authMocker.ClassUnderTest.GetCategories(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new CategoriesParametersModel(); - - //Arange - _authMocker.Get() - .Expect(x => x.GetCategories(parameters.Ids, - parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.UpdatedAtMin, - parameters.UpdatedAtMax, - parameters.Limit, - parameters.Page, - parameters.SinceId, - parameters.ProductId, - parameters.PublishedStatus)).Return(new List()); - - //Act - _authMocker.ClassUnderTest.GetCategories(parameters); - - //Assert - _authMocker.Get().VerifyAllExpectations(); - } - - // The static method category.GetSeName() breaks this test as we can't stub static methods :( - //[Test] - //public void WhenSomeCategoriesExist_ShouldCallTheSerializerWithTheseCategories() - //{ - // MappingExtensions.Maps.CreateMap(); - - // var returnedCategoriesCollection = new List() - // { - // new Category(), - // new Category() - // }; - - // var parameters = new CategoriesParametersModel(); - - // //Arange - // var autoMocker = new RhinoAutoMocker(); - // autoMocker.Get().Stub(x => x.GetCategories()).Return(returnedCategoriesCollection); - // autoMocker.Get().Stub(x => x.GetAclRecords(new Category())).IgnoreArguments().Return(new List()); - // autoMocker.Get().Stub(x => x.GetStoreMappings(new Category())).IgnoreArguments().Return(new List()); - - // //Act - // autoMocker.ClassUnderTest.GetCategories(parameters); - - // //Assert - // autoMocker.Get().AssertWasCalled( - // x => x.Serialize(Arg.Matches(r => r.Categories.Count == 2), - // Arg.Is.Equal(parameters.Fields))); - //} - - [Test] - public void WhenAnyFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var parameters = new CategoriesParametersModel() - { - Fields = "id,name" - }; - - //Arange - _authMocker.Get().Stub(x => x.GetCategories()).Return(new List()); - - //Act - _authMocker.ClassUnderTest.GetCategories(parameters); - - //Assert - _authMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenNoCategoriesExist_ShouldCallTheSerializerWithRootObjectWithoutCategories() - { - var parameters = new CategoriesParametersModel(); - - //Arange - _authMocker.Get().Stub(x => x.GetCategories()).Return(new List()); - - //Act - _authMocker.ClassUnderTest.GetCategories(parameters); - - //Assert - _authMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.Categories.Count == 0), - Arg.Is.Equal(parameters.Fields))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesById.cs b/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesById.cs deleted file mode 100644 index d1ab6e4..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesById.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Net; -using AutoMock; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Categories -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class CategoriesControllerTests_GetCategoriesById - { - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldReturnBadRequest(int nonPositiveCategoryId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetCategoryById(nonPositiveCategoryId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldNotCallCategoryApiService(int negativeCategoryId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - - // Act - autoMocker.ClassUnderTest.GetCategoryById(negativeCategoryId); - - // Assert - autoMocker.Get().AssertWasNotCalled(x => x.GetCategoryById(negativeCategoryId)); - } - - [Test] - public void WhenIdIsPositiveNumberButNoSuchCategoryExists_ShouldReturn404NotFound() - { - int nonExistingCategoryId = 5; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCategoryById(nonExistingCategoryId)).Return(null); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetCategoryById(nonExistingCategoryId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.NotFound, statusCode); - } - - // The static method category.GetSeName() breaks this test as we can't stub static methods :( - //[Test] - //public void WhenIdEqualsToExistingCategoryId_ShouldSerializeThatCategory() - //{ - // MappingExtensions.Maps.CreateMap(); - - // int existingCategoryId = 5; - // var existingCategory = new Category() { Id = existingCategoryId }; - - // // Arange - // var autoMocker = new RhinoAutoMocker(); - // autoMocker.Get().Stub(x => x.GetCategoryById(existingCategoryId)).Return(existingCategory); - // autoMocker.Get().Stub(x => x.GetAclRecords(new Category())).IgnoreArguments().Return(new List()); - // autoMocker.Get().Stub(x => x.GetStoreMappings(new Category())).IgnoreArguments().Return(new List()); - - // // Act - // autoMocker.ClassUnderTest.GetCategoryById(existingCategoryId); - - // // Assert - // autoMocker.Get().AssertWasCalled( - // x => x.Serialize( - // Arg.Matches( - // objectToSerialize => - // objectToSerialize.Categories.Count == 1 && - // objectToSerialize.Categories[0].Id == existingCategory.Id.ToString() && - // objectToSerialize.Categories[0].Name == existingCategory.Name), - // Arg.Is.Equal(""))); - //} - - // The static method category.GetSeName() breaks this test as we can't stub static methods - //[Test] - //public void WhenIdEqualsToExistingCategoryIdAndFieldsSet_ShouldReturnJsonForThatCategoryWithSpecifiedFields() - //{ - // MappingExtensions.Maps.CreateMap(); - - // int existingCategoryId = 5; - // var existingCategory = new Category() { Id = existingCategoryId, Name = "some category name" }; - // string fields = "id,name"; - - // // Arange - // var autoMocker = new RhinoAutoMocker(); - // autoMocker.Get().Stub(x => x.GetCategoryById(existingCategoryId)).Return(existingCategory); - // autoMocker.Get().Stub(x => x.GetAclRecords(new Category())).IgnoreArguments().Return(new List()); - // autoMocker.Get().Stub(x => x.GetStoreMappings(new Category())).IgnoreArguments().Return(new List()); - - // // Act - // autoMocker.ClassUnderTest.GetCategoryById(existingCategoryId, fields); - - // // Assert - // autoMocker.Get().AssertWasCalled( - // x => x.Serialize( - // Arg.Matches(objectToSerialize => objectToSerialize.Categories[0].Id == existingCategory.Id.ToString() && - // objectToSerialize.Categories[0].Name == existingCategory.Name), - // Arg.Matches(fieldsParameter => fieldsParameter == fields))); - //} - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesCount.cs b/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesCount.cs deleted file mode 100644 index aa62ecf..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Categories/CategoriesControllerTests_GetCategoriesCount.cs +++ /dev/null @@ -1,101 +0,0 @@ -using AutoMock; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.Models.CategoriesParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Categories -{ - using Microsoft.AspNetCore.Mvc; - - [TestFixture] - public class CategoriesControllerTests_GetCategoriesCount - { - [Test] - public void WhenNoCategoriesExist_ShouldReturnOKResultWithCountEqualToZero() - { - var parameters = new CategoriesCountParametersModel(); - - // arrange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.GetCategoriesCount()).IgnoreArguments().Return(0); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCategoriesCount(parameters); - - // assert - Assert.IsInstanceOf(result); - - var okObjectResult = result as OkObjectResult; - - Assert.NotNull(okObjectResult); - - Assert.IsInstanceOf(okObjectResult.Value); - - var rootObject = okObjectResult.Value as CategoriesCountRootObject; - - Assert.NotNull(rootObject); - - Assert.AreEqual(0, rootObject.Count); - } - - [Test] - public void WhenSingleCategoryExists_ShouldReturnOKWithCountEqualToOne() - { - var parameters = new CategoriesCountParametersModel(); - - // arrange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.GetCategoriesCount()).IgnoreArguments().Return(1); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCategoriesCount(parameters); - - // assert - Assert.IsInstanceOf(result); - - var okObjectResult = result as OkObjectResult; - - Assert.NotNull(okObjectResult); - - Assert.IsInstanceOf(okObjectResult.Value); - - var rootObject = okObjectResult.Value as CategoriesCountRootObject; - - Assert.NotNull(rootObject); - - Assert.AreEqual(1, rootObject.Count); - } - - [Test] - public void WhenCertainNumberOfCategoriesExist_ShouldReturnOKWithCountEqualToSameNumberOfCategories() - { - var categoriesCountParametersModel = new CategoriesCountParametersModel(); - int categoriesCount = 20; - - // arrange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.GetCategoriesCount()).IgnoreArguments().Return(categoriesCount); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCategoriesCount(categoriesCountParametersModel); - - // assert - Assert.IsInstanceOf(result); - - var okObjectResult = result as OkObjectResult; - - Assert.NotNull(okObjectResult); - - Assert.IsInstanceOf(okObjectResult.Value); - - var rootObject = okObjectResult.Value as CategoriesCountRootObject; - - Assert.NotNull(rootObject); - - Assert.AreEqual(categoriesCount, rootObject.Count); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomerById.cs b/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomerById.cs deleted file mode 100644 index 1f8bb21..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomerById.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Net; -using AutoMock; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Customers -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class CustomersControllerTests_GetCustomerById - { - [Test] - public void WhenIdIsPositiveNumberButNoSuchCustmerWithSuchIdExists_ShouldReturn404NotFound() - { - int nonExistingCustomerId = 5; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCustomerById(nonExistingCustomerId)).Return(null); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetCustomerById(nonExistingCustomerId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.NotFound, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldReturnBadRequest(int nonPositiveCustomerId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetCustomerById(nonPositiveCustomerId); - - // Assert - - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldNotCallCustomerApiService(int negativeCustomerId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - // Act - autoMocker.ClassUnderTest.GetCustomerById(negativeCustomerId); - - // Assert - autoMocker.Get().AssertWasNotCalled(x => x.GetCustomerById(negativeCustomerId)); - } - - [Test] - public void WhenIdEqualsToExistingCustomerId_ShouldSerializeThatCustomer() - { - int existingCustomerId = 5; - CustomerDto existingCustomerDto = new CustomerDto() { Id = existingCustomerId.ToString() }; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCustomerById(existingCustomerId)).Return(existingCustomerDto); - - // Act - autoMocker.ClassUnderTest.GetCustomerById(existingCustomerId); - - // Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize( - Arg.Matches(objectToSerialize => objectToSerialize.Customers[0] == existingCustomerDto), - Arg.Matches(fields => fields == ""))); - } - - [Test] - public void WhenIdEqualsToExistingCustomerIdAndFieldsSet_ShouldReturnJsonForThatCustomerWithSpecifiedFields() - { - int existingCustomerId = 5; - CustomerDto existingCustomerDto = new CustomerDto() { Id = existingCustomerId.ToString() }; - string fields = "id,email"; - - // Arange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.GetCustomerById(existingCustomerId)).Return(existingCustomerDto); - - // Act - autoMocker.ClassUnderTest.GetCustomerById(existingCustomerId, fields); - - // Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize( - Arg.Matches(objectToSerialize => objectToSerialize.Customers[0] == existingCustomerDto), - Arg.Matches(fieldsParameter => fieldsParameter == fields))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomers.cs b/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomers.cs deleted file mode 100644 index 3a74c17..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomers.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Models.CustomersParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Customers -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class CustomersControllerTests_GetCustomers - { - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new CustomersParametersModel() - { - SinceId = Configurations.DefaultSinceId + 1, // some different than default since id - CreatedAtMin = DateTime.Now, - CreatedAtMax = DateTime.Now, - Page = Configurations.DefaultPageValue + 1, // some different than default page - Limit = Configurations.MinLimit + 1 // some different than default limit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - //Act - autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - autoMocker.Get().AssertWasCalled(x => x.GetCustomersDtos(parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.Limit, - parameters.Page, - parameters.SinceId)); - } - - [Test] - public void WhenSomeCustomersExist_ShouldCallTheSerializerWithTheseCustomers() - { - var returnedCustomersDtoCollection = new List() - { - new CustomerDto(), - new CustomerDto() - }; - - var parameters = new CustomersParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCustomersDtos()).Return(returnedCustomersDtoCollection); - - //Act - autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.Customers.Count == returnedCustomersDtoCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenNoCustomersExist_ShouldCallTheSerializerWithNoCustomers() - { - var returnedCustomersDtoCollection = new List(); - - var parameters = new CustomersParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCustomersDtos()).Return(returnedCustomersDtoCollection); - - //Act - autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.Customers.Count == returnedCustomersDtoCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var parameters = new CustomersParametersModel() - { - Fields = "id,email" - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - //Act - autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); - } - - [Test] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parameters = new CustomersParametersModel() - { - Limit = invalidLimit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) - { - var parameters = new CustomersParametersModel() - { - Page = invalidPage - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetCustomers(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomersCount.cs b/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomersCount.cs deleted file mode 100644 index dd131cd..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_GetCustomersCount.cs +++ /dev/null @@ -1,67 +0,0 @@ -using AutoMock; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Customers -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - - [TestFixture] - public class CustomersControllerTests_GetCustomersCount - { - [Test] - public void WhenNoCustomersExist_ShouldReturnOKResultWithCountEqualToZero() - { - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - autoMocker.Get().Stub(x => x.GetCustomersCount()).Return(0); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCustomersCount(); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(0, ((CustomersCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenSingleCustomerExists_ShouldReturnOKWithCountEqualToOne() - { - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - autoMocker.Get().Stub(x => x.GetCustomersCount()).Return(1); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCustomersCount(); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(1, ((CustomersCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenCertainNumberOfCustomersExist_ShouldReturnOKWithCountEqualToSameNumberOfCustomers() - { - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetCustomersCount()).Return(20000); - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetCustomersCount(); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(20000, ((CustomersCountRootObject)((OkObjectResult)result).Value).Count); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_Search.cs b/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_Search.cs deleted file mode 100644 index e93122f..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Customers/CustomersControllerTests_Search.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Models.CustomersParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Customers -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class CustomersControllerTests_Search - { - [Test] - public void WhenNoParametersPassed_ShouldCallTheServiceWithDefaultParameters() - { - var defaultParametersModel = new CustomersSearchParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - //Act - autoMocker.ClassUnderTest.Search(defaultParametersModel); - - //Assert - autoMocker.Get().AssertWasCalled(x => x.Search(defaultParametersModel.Query, - defaultParametersModel.Order, - defaultParametersModel.Page, - defaultParametersModel.Limit)); - } - - [Test] - public void WhenNoParametersPassedAndSomeCustomersExist_ShouldCallTheSerializer() - { - var expectedCustomersCollection = new List() - { - new CustomerDto(), - new CustomerDto() - }; - - var expectedRootObject = new CustomersRootObject() - { - Customers = expectedCustomersCollection - }; - - var defaultParameters = new CustomersSearchParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Expect(x => x.Serialize(expectedRootObject, defaultParameters.Fields)); - autoMocker.Get().Stub(x => x.Search()).Return(expectedCustomersCollection); - - //Act - autoMocker.ClassUnderTest.Search(defaultParameters); - - //Assert - autoMocker.Get().AssertWasCalled(x => x.Serialize(Arg.Is.TypeOf, - Arg.Is.Equal(defaultParameters.Fields))); - } - - [Test] - public void WhenNoParametersPassedAndNoCustomersExist_ShouldCallTheSerializer() - { - var expectedCustomersCollection = new List(); - - var expectedRootObject = new CustomersRootObject() - { - Customers = expectedCustomersCollection - }; - - var defaultParameters = new CustomersSearchParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Expect(x => x.Serialize(expectedRootObject, defaultParameters.Fields)); - autoMocker.Get().Stub(x => x.Search()).Return(expectedCustomersCollection); - - //Act - autoMocker.ClassUnderTest.Search(defaultParameters); - - //Assert - autoMocker.Get().AssertWasCalled(x => x.Serialize(Arg.Is.TypeOf, - Arg.Is.Equal(defaultParameters.Fields))); - } - - [Test] - public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var defaultParametersModel = new CustomersSearchParametersModel() - { - Fields = "id,email" - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - //Act - autoMocker.ClassUnderTest.Search(defaultParametersModel); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(defaultParametersModel.Fields))); - } - - [Test] - [TestCase(Configurations.MinLimit)] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parametersModel = new CustomersSearchParametersModel() - { - Limit = invalidLimit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.Search(parametersModel); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenNonPositivePagePassed_ShouldReturnBadRequest(int nonPositivePage) - { - var parametersModel = new CustomersSearchParametersModel() - { - Limit = nonPositivePage - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.Search(parametersModel); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrderById.cs b/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrderById.cs deleted file mode 100644 index 3d2cdd5..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrderById.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Net; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Orders -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class OrdersControllerTests_GetOrderById - { - [Test] - public void WhenIdIsPositiveNumberButNoSuchOrderWithSuchIdExists_ShouldReturn404NotFound() - { - int nonExistingOrderId = 5; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetOrderById(nonExistingOrderId)).Return(null); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetOrderById(nonExistingOrderId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.NotFound, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldReturnBadRequest(int nonPositiveOrderId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetOrderById(nonPositiveOrderId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldNotCallOrderApiService(int negativeOrderId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - // Act - autoMocker.ClassUnderTest.GetOrderById(negativeOrderId); - - // Assert - autoMocker.Get().AssertWasNotCalled(x => x.GetOrderById(negativeOrderId)); - } - - [Test] - public void WhenIdEqualsToExistingOrderId_ShouldSerializeThatOrder() - { - int existingOrderId = 5; - var existingOrder = new Order() { Id = existingOrderId }; - var existingOrderDto = new OrderDto() { Id = existingOrderId.ToString() }; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetOrderById(existingOrderId)).Return(existingOrder); - autoMocker.Get().Stub(x => x.PrepareOrderDTO(existingOrder)).Return(existingOrderDto); - - // Act - autoMocker.ClassUnderTest.GetOrderById(existingOrderId); - - // Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize( - Arg.Matches(objectToSerialize => objectToSerialize.Orders[0].Id == existingOrderId.ToString()), - Arg.Matches(fields => fields == ""))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrders.cs b/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrders.cs deleted file mode 100644 index 7488eff..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrders.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.Models.OrdersParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Orders -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Core; - using Nop.Core.Domain.Stores; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class OrdersControllerTests_GetOrders - { - private RhinoAutoMocker _autoMocker; - - [SetUp] - public void StartUp() - { - _autoMocker = new RhinoAutoMocker(); - _autoMocker.Get().Stub(x => x.CurrentStore).Return(new Store()); - } - - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new OrdersParametersModel() - { - SinceId = Configurations.DefaultSinceId + 1, // some different than default since id - CreatedAtMin = DateTime.Now, - CreatedAtMax = DateTime.Now, - Page = Configurations.DefaultPageValue + 1, // some different than default page - Limit = Configurations.MinLimit + 1, // some different than default limit - Ids = new List() {1, 2, 3} - }; - - //Arange - _autoMocker.Get() - .Expect(x => x.GetOrders(parameters.Ids, - parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.Limit, - parameters.Page, - parameters.SinceId)).IgnoreArguments().Return(new List()); - - //Act - _autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - _autoMocker.Get().VerifyAllExpectations(); - } - - [Test] - public void WhenSomeOrdersExist_ShouldCallTheSerializerWithTheseOrders() - { - var returnedOrdersCollection = new List() - { - new Order(), - new Order() - }; - - var parameters = new OrdersParametersModel(); - - //Arange - _autoMocker.Get().Stub(x => x.GetOrders()).IgnoreArguments().Return(returnedOrdersCollection); - - //Act - _autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - _autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.Orders.Count == returnedOrdersCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenNoOrdersExist_ShouldCallTheSerializerWithNoOrders() - { - var returnedOrdersDtoCollection = new List(); - - var parameters = new OrdersParametersModel(); - - //Arange - _autoMocker.Get().Stub(x => x.GetOrders()).IgnoreArguments().Return(returnedOrdersDtoCollection); - - //Act - _autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - _autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.Orders.Count == returnedOrdersDtoCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var parameters = new OrdersParametersModel() - { - Fields = "id,paymentstatus" - }; - - var returnedOrdersDtoCollection = new List(); - - //Arange - _autoMocker.Get().Stub(x => x.GetOrders()).IgnoreArguments().Return(returnedOrdersDtoCollection); - - //Act - _autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - _autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); - } - - [Test] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parameters = new OrdersParametersModel() - { - Limit = invalidLimit - }; - - //Arange - _autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = _autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) - { - var parameters = new OrdersParametersModel() - { - Page = invalidPage - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetOrders(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersByCustomerId.cs b/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersByCustomerId.cs deleted file mode 100644 index 7d25ad0..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersByCustomerId.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Orders -{ - [TestFixture] - public class OrdersControllerTests_GetOrdersByCustomerId - { - [Test] - [TestCase(-5)] - [TestCase(0)] - [TestCase(10)] - [TestCase(int.MaxValue)] - public void WhenCustomerIdIsPassed_ShouldCallTheServiceWithThePassedParameters(int customerId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Expect(x => x.GetOrdersByCustomerId(customerId)).Return(new List()); - - // Act - autoMocker.ClassUnderTest.GetOrdersByCustomerId(customerId); - - // Assert - autoMocker.Get().VerifyAllExpectations(); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersCount.cs b/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersCount.cs deleted file mode 100644 index 686fc1b..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Orders/OrdersControllerTests_GetOrdersCount.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.Models.OrdersParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.Orders -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Core; - using Nop.Core.Domain.Stores; - using Nop.Plugin.Api.DTOs.Orders; - using Nop.Plugin.Api.JSON.Serializers; - - [TestFixture] - public class OrdersControllerTests_GetOrdersCount - { - private RhinoAutoMocker _autoMocker; - - [SetUp] - public void StartUp() - { - _autoMocker = new RhinoAutoMocker(); - _autoMocker.Get().Stub(x => x.CurrentStore).Return(new Store()); - } - - [Test] - public void WhenNoOrdersExist_ShouldReturnOKResultWithCountEqualToZero() - { - // arrange - var ordersCountParameters = new OrdersCountParametersModel(); - - _autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - _autoMocker.Get().Stub(x => x.GetOrdersCount()).IgnoreArguments().Return(0); - - // act - IActionResult result = _autoMocker.ClassUnderTest.GetOrdersCount(ordersCountParameters); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(0, ((OrdersCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenSingleOrderExists_ShouldReturnOKWithCountEqualToOne() - { - // arrange - var ordersCountParameters = new OrdersCountParametersModel(); - - _autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - _autoMocker.Get().Stub(x => x.GetOrdersCount()).IgnoreArguments().Return(1); - - // act - IActionResult result = _autoMocker.ClassUnderTest.GetOrdersCount(ordersCountParameters); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(1, ((OrdersCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenCertainNumberOfOrdersExist_ShouldReturnOKWithCountEqualToSameNumberOfOrders() - { - // arrange - var ordersCountParameters = new OrdersCountParametersModel(); - - _autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - _autoMocker.Get().Stub(x => x.GetOrdersCount()).IgnoreArguments().Return(20000); - - // act - IActionResult result = _autoMocker.ClassUnderTest.GetOrdersCount(ordersCountParameters); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(20000, ((OrdersCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new OrdersCountParametersModel() - { - CreatedAtMin = DateTime.Now, - CreatedAtMax = DateTime.Now, - Status = OrderStatus.Complete, - ShippingStatus = ShippingStatus.Delivered, - PaymentStatus = PaymentStatus.Authorized, - CustomerId = 10 - }; - - //Arange - _autoMocker.Get().Expect(x => x.GetOrdersCount(parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.Status, - parameters.PaymentStatus, - parameters.ShippingStatus, - parameters.CustomerId)).IgnoreArguments().Return(1); - - //Act - _autoMocker.ClassUnderTest.GetOrdersCount(parameters); - - //Assert - _autoMocker.Get().VerifyAllExpectations(); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidCustomerIdParameterPassed_ShouldCallTheServiceWithThisCustomerId(int invalidCustomerId) - { - var parameters = new OrdersCountParametersModel() - { - CustomerId = invalidCustomerId - }; - - //Arange - _autoMocker.Get().Expect(x => x.GetOrdersCount(parameters.CreatedAtMin, - parameters.CreatedAtMax, - parameters.Status, - parameters.PaymentStatus, - parameters.ShippingStatus, - parameters.CustomerId)).IgnoreArguments().Return(0); - - //Act - _autoMocker.ClassUnderTest.GetOrdersCount(parameters); - - //Assert - _autoMocker.Get().VerifyAllExpectations(); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingById.cs b/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingById.cs deleted file mode 100644 index 02dedbd..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingById.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.Net; -using AutoMock; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.ProductCategoryMappings -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class ProductCategoryMappingsControllerTests_GetMappingById - { - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldReturnBadRequest(int nonPositiveProductCategoryMappingId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetMappingById(nonPositiveProductCategoryMappingId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldNotCallProductCategoryMappingsApiService(int nonPositiveProductCategoryMappingId) - { - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - - // Act - autoMocker.ClassUnderTest.GetMappingById(nonPositiveProductCategoryMappingId); - - // Assert - autoMocker.Get().AssertWasNotCalled(x => x.GetById(nonPositiveProductCategoryMappingId)); - } - - [Test] - public void WhenIdIsPositiveNumberButNoSuchMappingExists_ShouldReturn404NotFound() - { - int nonExistingMappingId = 5; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetById(nonExistingMappingId)).Return(null); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetMappingById(nonExistingMappingId); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.NotFound, statusCode); - } - - [Test] - public void WhenIdEqualsToExistingMappingId_ShouldSerializeThatMapping() - { - //MappingExtensions.Maps.CreateMap(); - - int existingMappingId = 5; - var existingMapping = new ProductCategory() { Id = existingMappingId }; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetById(existingMappingId)).Return(existingMapping); - - // Act - autoMocker.ClassUnderTest.GetMappingById(existingMappingId); - - // Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize( - Arg.Matches( - objectToSerialize => - objectToSerialize.ProductCategoryMappingDtos.Count == 1 && - objectToSerialize.ProductCategoryMappingDtos[0].Id == existingMapping.Id), - Arg.Is.Equal(""))); - } - - [Test] - public void WhenIdEqualsToExistingProductCategoryMappingIdAndFieldsSet_ShouldReturnJsonForThatProductCategoryMappingWithSpecifiedFields() - { - //MappingExtensions.Maps.CreateMap(); - - int existingMappingId = 5; - var existingMapping = new ProductCategory() { Id = existingMappingId }; - string fields = "id,name"; - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetById(existingMappingId)).Return(existingMapping); - - // Act - autoMocker.ClassUnderTest.GetMappingById(existingMappingId, fields); - - // Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize( - Arg.Matches(objectToSerialize => objectToSerialize.ProductCategoryMappingDtos[0].Id == existingMapping.Id), - Arg.Matches(fieldsParameter => fieldsParameter == fields))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappings.cs b/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappings.cs deleted file mode 100644 index 3991fa2..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappings.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.Models.ProductCategoryMappingsParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.ProductCategoryMappings -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class ProductCategoryMappingsControllerTests_GetMappings - { - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new ProductCategoryMappingsParametersModel() - { - SinceId = Configurations.DefaultSinceId + 1, // some different than default since id - Page = Configurations.DefaultPageValue + 1, // some different than default page - Limit = Configurations.MinLimit + 1 // some different than default limit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Expect(x => x.GetMappings(parameters.ProductId, - parameters.CategoryId, - parameters.Limit, - parameters.Page, - parameters.SinceId)).Return(new List()); - - //Act - autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - autoMocker.Get().VerifyAllExpectations(); - } - - [Test] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parameters = new ProductCategoryMappingsParametersModel() - { - Limit = invalidLimit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) - { - var parameters = new ProductCategoryMappingsParametersModel() - { - Page = invalidPage - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - public void WhenNoProductCategoryMappingsExist_ShouldCallTheSerializerWithNoProductCategoryMappings() - { - var returnedMappingsCollection = new List(); - - var parameters = new ProductCategoryMappingsParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappings()).IgnoreArguments().Return(returnedMappingsCollection); - - //Act - autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - autoMocker.Get< IJsonFieldsSerializer>().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.ProductCategoryMappingDtos.Count == returnedMappingsCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var parameters = new ProductCategoryMappingsParametersModel() - { - Fields = "id,product_id" - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappings()).Return(new List()); - - //Act - autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenSomeProductCategoryMappingsExist_ShouldCallTheSerializerWithTheseProductCategoryMappings() - { - //MappingExtensions.Maps.CreateMap(); - - var returnedMappingsDtoCollection = new List() - { - new ProductCategory(), - new ProductCategory() - }; - - var parameters = new ProductCategoryMappingsParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappings()).Return(returnedMappingsDtoCollection); - - //Act - autoMocker.ClassUnderTest.GetMappings(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.ProductCategoryMappingDtos.Count == returnedMappingsDtoCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingsCount.cs b/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingsCount.cs deleted file mode 100644 index c87dafc..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/ProductCategoryMappings/ProductCategoryMappingsControllerTests_GetMappingsCount.cs +++ /dev/null @@ -1,70 +0,0 @@ -using AutoMock; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.Models.ProductCategoryMappingsParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.ProductCategoryMappings -{ - using Microsoft.AspNetCore.Mvc; - - [TestFixture] - public class ProductCategoryMappingsControllerTests_GetMappingsCount - { - [Test] - public void WhenNoProductCategoryMappingsExist_ShouldReturnOKResultWithCountEqualToZero() - { - var parameters = new ProductCategoryMappingsCountParametersModel(); - - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappingsCount()).IgnoreArguments().Return(0); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetMappingsCount(parameters); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(0, ((ProductCategoryMappingsCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenSingleProductCategoryMappingExists_ShouldReturnOKWithCountEqualToOne() - { - var parameters = new ProductCategoryMappingsCountParametersModel(); - - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappingsCount()).IgnoreArguments().Return(1); - // act - IActionResult result = autoMocker.ClassUnderTest.GetMappingsCount(parameters); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(1, ((ProductCategoryMappingsCountRootObject)((OkObjectResult)result).Value).Count); - } - - [Test] - public void WhenCertainNumberOfProductCategoryMappingsExist_ShouldReturnOKWithCountEqualToSameNumberOfProductCategoryMappings() - { - var mappingsCountParametersModel = new ProductCategoryMappingsCountParametersModel(); - int mappingsCount = 20; - - // arrange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetMappingsCount()).IgnoreArguments().Return(mappingsCount); - - // act - IActionResult result = autoMocker.ClassUnderTest.GetMappingsCount(mappingsCountParametersModel); - - // assert - Assert.IsInstanceOf(result); - Assert.AreEqual(mappingsCount, ((ProductCategoryMappingsCountRootObject)((OkObjectResult)result).Value).Count); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductById.cs b/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductById.cs deleted file mode 100644 index 8aa167b..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductById.cs +++ /dev/null @@ -1,110 +0,0 @@ -//using Nop.Core.Domain.Catalog; -//using Nop.Plugin.Api.Controllers; -//using Nop.Plugin.Api.DTOs.Products; -//using Nop.Plugin.Api.Services; -//using NUnit.Framework; -//using Rhino.Mocks; - -//namespace Nop.Plugin.Api.Tests.ControllersTests.Products -//{ -// using AutoMock; -// using Microsoft.AspNetCore.Mvc; -// using Nop.Plugin.Api.JSON.Serializers; - -// [TestFixture] -// public class ProductsControllerTests_GetProductById -// { -// [Test] -// [TestCase(0)] -// [TestCase(-20)] -// public void WhenIdEqualsToZeroOrLess_ShouldReturn404NotFound(int nonPositiveProductId) -// { -// // Arange -// var autoMocker = new RhinoAutoMocker(); - -// // Act -// IActionResult result = autoMocker.ClassUnderTest.GetProductById(nonPositiveProductId); - -// // Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// [TestCase(0)] -// [TestCase(-20)] -// public void WhenIdEqualsToZeroOrLess_ShouldNotCallProductApiService(int negativeProductId) -// { -// // Arange -// var autoMocker = new RhinoAutoMocker(); -// autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - -// // Act -// autoMocker.ClassUnderTest.GetProductById(negativeProductId); - -// // Assert -// autoMocker.Get().AssertWasNotCalled(x => x.GetProductById()); -// } - -// [Test] -// public void WhenIdIsPositiveNumberButNoSuchProductExists_ShouldReturn404NotFound() -// { -// int nonExistingProductId = 5; - -// // Arange -// var autoMocker = new RhinoAutoMocker(); -// autoMocker.Get().Stub(x => x.GetProductById(nonExistingProductId)).Return(null); - -// // Act -// IActionResult result = autoMocker.ClassUnderTest.GetProductById(nonExistingProductId); - -// // Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// public void WhenIdEqualsToExistingProductId_ShouldSerializeThatProduct() -// { -// int existingProductId = 5; -// var existingProduct = new Product() { Id = existingProductId }; - -// // Arange -// var autoMocker = new RhinoAutoMocker(); -// autoMocker.Get().Stub(x => x.GetProductById(existingProductId)).Return(existingProduct); - -// // Act -// autoMocker.ClassUnderTest.GetProductById(existingProductId); - -// // Assert -// autoMocker.Get().AssertWasCalled( -// x => x.Serialize( -// Arg.Matches( -// objectToSerialize => -// objectToSerialize.Products.Count == 1 && -// objectToSerialize.Products[0].Id == existingProduct.Id.ToString() && -// objectToSerialize.Products[0].Name == existingProduct.Name), -// Arg.Is.Equal(""))); -// } - -// [Test] -// public void WhenIdEqualsToExistingProductIdAndFieldsSet_ShouldReturnJsonForThatProductWithSpecifiedFields() -// { -// int existingProductId = 5; -// var existingProduct = new Product() { Id = existingProductId, Name = "some product name" }; -// string fields = "id,name"; - -// // Arange -// var autoMocker = new RhinoAutoMocker(); -// autoMocker.Get().Stub(x => x.GetProductById(existingProductId)).Return(existingProduct); - -// // Act -// autoMocker.ClassUnderTest.GetProductById(existingProductId, fields); - -// // Assert -// autoMocker.Get().AssertWasCalled( -// x => x.Serialize( -// Arg.Matches(objectToSerialize => objectToSerialize.Products[0].Id == existingProduct.Id.ToString() && -// objectToSerialize.Products[0].Name == existingProduct.Name), -// Arg.Matches(fieldsParameter => fieldsParameter == fields))); -// } -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProducts.cs b/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProducts.cs deleted file mode 100644 index 820dd6a..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProducts.cs +++ /dev/null @@ -1,177 +0,0 @@ -//using System.Collections.Generic; -//using System.Web.Http; -//using System.Web.Http.Results; -//using Nop.Core.Domain.Catalog; -//using Nop.Plugin.Api.Constants; -//using Nop.Plugin.Api.Controllers; -//using Nop.Plugin.Api.DTOs.Products; -//using Nop.Plugin.Api.MappingExtensions; -//using Nop.Plugin.Api.Models.ProductsParameters; -//using Nop.Plugin.Api.Serializers; -//using Nop.Plugin.Api.Services; -//using NUnit.Framework; -//using Rhino.Mocks; - -//namespace Nop.Plugin.Api.Tests.ControllersTests.Products -//{ -// [TestFixture] -// public class ProductsControllerTests_GetProducts -// { -// [Test] -// [TestCase(Configurations.MinLimit - 1)] -// [TestCase(Configurations.MaxLimit + 1)] -// public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) -// { -// var parameters = new ProductsParametersModel() -// { -// Limit = invalidLimit -// }; - -// //Arange -// IProductApiService productApiServiceStub = MockRepository.GenerateStub(); - -// IJsonFieldsSerializer jsonFieldsSerializerStub = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productApiServiceStub, jsonFieldsSerializerStub); - -// //Act -// IActionResult result = cut.GetProducts(parameters); - -// //Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// [TestCase(-1)] -// [TestCase(0)] -// public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) -// { -// var parameters = new ProductsParametersModel() -// { -// Page = invalidPage -// }; - -// //Arange -// IProductApiService productApiServiceStub = MockRepository.GenerateStub(); - -// IJsonFieldsSerializer jsonFieldsSerializerStub = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productApiServiceStub, jsonFieldsSerializerStub); - -// //Act -// IActionResult result = cut.GetProducts(parameters); - -// //Assert -// Assert.IsInstanceOf(result); -// } - -// [Test] -// public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() -// { -// var parameters = new ProductsParametersModel(); - -// //Arange -// IProductApiService productsApiServiceMock = MockRepository.GenerateMock(); - -// productsApiServiceMock.Expect(x => x.GetProducts(parameters.Ids, -// parameters.CreatedAtMin, -// parameters.CreatedAtMax, -// parameters.UpdatedAtMin, -// parameters.UpdatedAtMax, -// parameters.Limit, -// parameters.Page, -// parameters.SinceId, -// parameters.CategoryId, -// parameters.VendorName, -// parameters.PublishedStatus)).Return(new List()); - -// IJsonFieldsSerializer jsonFieldsSerializer = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productsApiServiceMock, jsonFieldsSerializer); - -// //Act -// cut.GetProducts(parameters); - -// //Assert -// productsApiServiceMock.VerifyAllExpectations(); -// } - -// [Test] -// public void WhenNoProductsExist_ShouldCallTheSerializerWithNoProducts() -// { -// var returnedProductsCollection = new List(); - -// var parameters = new ProductsParametersModel(); - -// //Arange -// IProductApiService productApiServiceStub = MockRepository.GenerateStub(); -// productApiServiceStub.Stub(x => x.GetProducts()).Return(returnedProductsCollection); - -// IJsonFieldsSerializer jsonFieldsSerializerMock = MockRepository.GenerateMock(); - -// var cut = new ProductsController(productApiServiceStub, jsonFieldsSerializerMock); - -// //Act -// cut.GetProducts(parameters); - -// //Assert -// jsonFieldsSerializerMock.AssertWasCalled( -// x => x.Serialize(Arg.Matches(r => r.Products.Count == returnedProductsCollection.Count), -// Arg.Is.Equal(parameters.Fields))); -// } - -// [Test] -// public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() -// { -// var parameters = new ProductsParametersModel() -// { -// Fields = "id,name" -// }; - -// //Arange -// IProductApiService productApiServiceStub = MockRepository.GenerateStub(); -// productApiServiceStub.Stub(x => x.GetProducts()).Return(new List()); - -// IJsonFieldsSerializer jsonFieldsSerializerMock = MockRepository.GenerateMock(); - -// var cut = new ProductsController(productApiServiceStub, jsonFieldsSerializerMock); - -// //Act -// cut.GetProducts(parameters); - -// //Assert -// jsonFieldsSerializerMock.AssertWasCalled( -// x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); -// } - -// [Test] -// public void WhenSomeProductsExist_ShouldCallTheSerializerWithTheseProducts() -// { -// Maps.CreateMap(); - -// var returnedProductsDtoCollection = new List() -// { -// new Product(), -// new Product() -// }; - -// var parameters = new ProductsParametersModel(); - -// //Arange -// IProductApiService productApiServiceStub = MockRepository.GenerateStub(); -// productApiServiceStub.Stub(x => x.GetProducts()).Return(returnedProductsDtoCollection); - -// IJsonFieldsSerializer jsonFieldsSerializerMock = MockRepository.GenerateMock(); - -// var cut = new ProductsController(productApiServiceStub, jsonFieldsSerializerMock); - -// //Act -// cut.GetProducts(parameters); - -// //Assert -// jsonFieldsSerializerMock.AssertWasCalled( -// x => x.Serialize(Arg.Matches(r => r.Products.Count == returnedProductsDtoCollection.Count), -// Arg.Is.Equal(parameters.Fields))); -// } -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductsCount.cs b/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductsCount.cs deleted file mode 100644 index 16006d1..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/Products/ProductsControllerTests_GetProductsCount.cs +++ /dev/null @@ -1,80 +0,0 @@ -//using System.Web.Http; -//using System.Web.Http.Results; -//using Nop.Plugin.Api.Controllers; -//using Nop.Plugin.Api.DTOs.Products; -//using Nop.Plugin.Api.Models.ProductsParameters; -//using Nop.Plugin.Api.Serializers; -//using Nop.Plugin.Api.Services; -//using NUnit.Framework; -//using Rhino.Mocks; - -//namespace Nop.Plugin.Api.Tests.ControllersTests.Products -//{ -// [TestFixture] -// public class ProductsControllerTests_GetProductsCount -// { -// [Test] -// public void WhenNoProductsExist_ShouldReturnOKResultWithCountEqualToZero() -// { -// var parameters = new ProductsCountParametersModel(); - -// // arrange -// var productsApiServiceStub = MockRepository.GenerateStub(); -// productsApiServiceStub.Stub(x => x.GetProductsCount()).IgnoreArguments().Return(0); - -// IJsonFieldsSerializer jsonFieldsSerializer = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productsApiServiceStub, jsonFieldsSerializer); - -// // act -// IActionResult result = cut.GetProductsCount(parameters); - -// // assert -// Assert.IsInstanceOf>(result); -// Assert.AreEqual(0, ((OkNegotiatedContentResult)result).Content.Count); -// } - -// [Test] -// public void WhenSingleProductExists_ShouldReturnOKWithCountEqualToOne() -// { -// var parameters = new ProductsCountParametersModel(); - -// // arrange -// var productsApiServiceStub = MockRepository.GenerateStub(); -// productsApiServiceStub.Stub(x => x.GetProductsCount()).IgnoreArguments().Return(1); - -// IJsonFieldsSerializer jsonFieldsSerializer = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productsApiServiceStub, jsonFieldsSerializer); - -// // act -// IActionResult result = cut.GetProductsCount(parameters); - -// // assert -// Assert.IsInstanceOf>(result); -// Assert.AreEqual(1, ((OkNegotiatedContentResult)result).Content.Count); -// } - -// [Test] -// public void WhenCertainNumberOfProductsExist_ShouldReturnOKWithCountEqualToSameNumberOfProducts() -// { -// var productsCountParametersModel = new ProductsCountParametersModel(); -// int productsCount = 20; - -// // arrange -// var productsApiServiceStub = MockRepository.GenerateStub(); -// productsApiServiceStub.Stub(x => x.GetProductsCount()).IgnoreArguments().Return(productsCount); - -// IJsonFieldsSerializer jsonFieldsSerializer = MockRepository.GenerateStub(); - -// var cut = new ProductsController(productsApiServiceStub, jsonFieldsSerializer); - -// // act -// IActionResult result = cut.GetProductsCount(productsCountParametersModel); - -// // assert -// Assert.IsInstanceOf>(result); -// Assert.AreEqual(productsCount, ((OkNegotiatedContentResult)result).Content.Count); -// } -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItems.cs b/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItems.cs deleted file mode 100644 index 57874d3..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItems.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.Models.ShoppingCartsParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.ShoppingCartItems -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class ShoppingCartItemsControllerTests_GetShoppingCartItems - { - [Test] - [TestCase(Configurations.MinLimit - 1)] - [TestCase(Configurations.MaxLimit + 1)] - public void WhenInvalidLimitParameterPassed_ShouldReturnBadRequest(int invalidLimit) - { - var parameters = new ShoppingCartItemsParametersModel() - { - Limit = invalidLimit - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - //Act - IActionResult result = autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(-1)] - [TestCase(0)] - public void WhenInvalidPageParameterPassed_ShouldReturnBadRequest(int invalidPage) - { - var parameters = new ShoppingCartItemsParametersModel() - { - Page = invalidPage - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - //Act - IActionResult result = autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - public void WhenSomeValidParametersPassed_ShouldCallTheServiceWithTheSameParameters() - { - var parameters = new ShoppingCartItemsParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Expect(x => x.GetShoppingCartItems(null, parameters.CreatedAtMin, - parameters.CreatedAtMax, parameters.UpdatedAtMin, - parameters.UpdatedAtMax, parameters.Limit, - parameters.Page)).Return(new List()); - - //Act - autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - autoMocker.Get().VerifyAllExpectations(); - } - - [Test] - public void WhenNoShoppingCartItemsExist_ShouldCallTheSerializerWithNoShoppingCartItems() - { - var returnedShoppingCartItemsCollection = new List(); - - var parameters = new ShoppingCartItemsParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetShoppingCartItems()).Return(returnedShoppingCartItemsCollection).IgnoreArguments(); - - //Act - autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.ShoppingCartItems.Count == returnedShoppingCartItemsCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenFieldsParametersPassed_ShouldCallTheSerializerWithTheSameFields() - { - var parameters = new ShoppingCartItemsParametersModel() - { - Fields = "id,quantity" - }; - - //Arange - var autoMocker = new RhinoAutoMocker(); - autoMocker.Get().Stub(x => x.GetShoppingCartItems()).Return(new List()).IgnoreArguments(); - - //Act - autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Is.Anything, Arg.Is.Equal(parameters.Fields))); - } - - [Test] - public void WhenSomeProductsExist_ShouldCallTheSerializerWithTheseProducts() - { - //MappingExtensions.Maps.CreateMap(); - - var returnedShoppingCartItemsDtoCollection = new List() - { - new ShoppingCartItem(), - new ShoppingCartItem() - }; - - var parameters = new ShoppingCartItemsParametersModel(); - - //Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetShoppingCartItems()).Return(returnedShoppingCartItemsDtoCollection).IgnoreArguments(); - //Act - autoMocker.ClassUnderTest.GetShoppingCartItems(parameters); - - //Assert - autoMocker.Get().AssertWasCalled( - x => x.Serialize(Arg.Matches(r => r.ShoppingCartItems.Count == returnedShoppingCartItemsDtoCollection.Count), - Arg.Is.Equal(parameters.Fields))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItemsByCustomerId.cs b/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItemsByCustomerId.cs deleted file mode 100644 index c3fbc44..0000000 --- a/Nop.Plugin.Api.Tests/ControllersTests/ShoppingCartItems/ShoppingCartItemsControllerTests_GetShoppingCartItemsByCustomerId.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using AutoMock; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Controllers; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.Models.ShoppingCartsParameters; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ControllersTests.ShoppingCartItems -{ - using Microsoft.AspNetCore.Mvc; - using Nop.Plugin.Api.Helpers; - using Nop.Plugin.Api.JSON.Serializers; - using Nop.Plugin.Api.Tests.Helpers; - - [TestFixture] - public class ShoppingCartItemsControllerTests_GetShoppingCartItemsByCustomerId - { - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldReturnBadRequest(int nonPositiveCustomerId) - { - // Arange - var parameters = new ShoppingCartItemsForCustomerParametersModel(); - - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetShoppingCartItemsByCustomerId(nonPositiveCustomerId, parameters); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.BadRequest, statusCode); - } - - [Test] - [TestCase(0)] - [TestCase(-20)] - public void WhenIdEqualsToZeroOrLess_ShouldNotCallShoppingCartItemsApiService(int negativeShoppingCartItemsId) - { - // Arange - var parameters = new ShoppingCartItemsForCustomerParametersModel(); - - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.Serialize(null, null)).Return(string.Empty); - - // Act - autoMocker.ClassUnderTest.GetShoppingCartItemsByCustomerId(negativeShoppingCartItemsId, parameters); - - // Assert - autoMocker.Get().AssertWasNotCalled(x => x.GetShoppingCartItems(negativeShoppingCartItemsId)); - } - - [Test] - public void WhenIdIsPositiveNumberButNoSuchShoppingCartItemsExists_ShouldReturn404NotFound() - { - int nonExistingShoppingCartItemId = 5; - var parameters = new ShoppingCartItemsForCustomerParametersModel(); - - // Arange - var autoMocker = new RhinoAutoMocker(); - - autoMocker.Get().Stub(x => x.GetShoppingCartItems(nonExistingShoppingCartItemId)).Return(null); - - autoMocker.Get().Stub(x => x.Serialize(Arg.Is.Anything, Arg.Is.Anything)) - .IgnoreArguments() - .Return(string.Empty); - - // Act - IActionResult result = autoMocker.ClassUnderTest.GetShoppingCartItemsByCustomerId(nonExistingShoppingCartItemId, parameters); - - // Assert - var statusCode = ActionResultExecutor.ExecuteResult(result); - - Assert.AreEqual(HttpStatusCode.NotFound, statusCode); - } - - //[Test] - //public void WhenIdEqualsToExistingShoppingCartItemId_ShouldSerializeThatShoppingCartItem() - //{ - // int existingShoppingCartItemId = 5; - // var existingShoppingCartItems = new List() - // { - // new ShoppingCartItem() {Id = existingShoppingCartItemId} - // }; - - // var parameters = new ShoppingCartItemsForCustomerParametersModel(); - - // // Arange - // var autoMocker = new RhinoAutoMocker(); - - // autoMocker.Get().Stub(x => x.GetShoppingCartItems(existingShoppingCartItemId)).Return(existingShoppingCartItems); - - // // Act - // autoMocker.ClassUnderTest.GetShoppingCartItemsByCustomerId(existingShoppingCartItemId, parameters); - - // // Assert - // autoMocker.Get().AssertWasCalled( - // x => x.Serialize( - // Arg.Matches( - // objectToSerialize => - // objectToSerialize.ShoppingCartItems.Count == 1 && - // objectToSerialize.ShoppingCartItems[0].Id == existingShoppingCartItemId.ToString()), - // Arg.Is.Equal(""))); - //} - - //[Test] - //public void WhenIdEqualsToExistingShoppingCartItemIdAndFieldsSet_ShouldReturnJsonForThatShoppingCartItemWithSpecifiedFields() - //{ - // int existingShoppingCartItemId = 5; - // var existingShoppingCartItems = new List() - // { - // new ShoppingCartItem() {Id = existingShoppingCartItemId} - // }; - - // var parameters = new ShoppingCartItemsForCustomerParametersModel() - // { - // Fields = "id,quantity" - // }; - - // // Arange - // var autoMocker = new RhinoAutoMocker(); - - // autoMocker.Get().Stub(x => x.GetShoppingCartItems(existingShoppingCartItemId)).Return(existingShoppingCartItems); - - // // Act - // autoMocker.ClassUnderTest.GetShoppingCartItemsByCustomerId(existingShoppingCartItemId, parameters); - - // // Assert - // autoMocker.Get().AssertWasCalled( - // x => x.Serialize( - // Arg.Matches(objectToSerialize => objectToSerialize.ShoppingCartItems[0].Id == existingShoppingCartItemId.ToString()), - // Arg.Matches(fieldsParameter => fieldsParameter == parameters.Fields))); - //} - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToDateTimeNullable.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToDateTimeNullable.cs deleted file mode 100644 index e806569..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToDateTimeNullable.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Globalization; -using Nop.Plugin.Api.Converters; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToDateTimeNullable - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("invalid date")] - [TestCase("20.30.10")] - [TestCase("2016-30-30")] - [TestCase("2016/78/12")] - [TestCase("2016/12/12")] - [TestCase("2016,12,34")] - [TestCase("&^%$&(^%$_+")] - [TestCase("2016,23,07")] - [TestCase("2016.23.07")] - [TestCase("2016.07.23")] - [TestCase("0")] - public void WhenInvalidDatePassed_ShouldReturnNull(string invalidDate) - { - //Arange - - //Act - DateTime? result = _apiTypeConverter.ToUtcDateTimeNullable(invalidDate); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnNull(string nullOrEmpty) - { - //Arange - - //Act - DateTime? result = _apiTypeConverter.ToUtcDateTimeNullable(nullOrEmpty); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("2016-12")] - [TestCase("2016-12-26")] - [TestCase("2016-12-26T06:45")] - [TestCase("2016-12-26T06:45:49")] - [TestCase("2016-12-26T06:45:49.05")] - public void WhenValidIso8601DateWithoutTimeZoneOrOffsetPassed_ShouldConvertAsUTC(string validDate) - { - //Arange - DateTime expectedDateTimeUtc = DateTime.Parse(validDate,null,DateTimeStyles.RoundtripKind); - - //Act - DateTime? result = _apiTypeConverter.ToUtcDateTimeNullable(validDate); - - //Assert - Assert.AreEqual(expectedDateTimeUtc, result); - } - - [TestCase("2016-12-26T06:45:49Z")] - [TestCase("2016-12-26T07:45:49+01:00")] - [TestCase("2016-12-26T08:45:49+02:00")] - [TestCase("2016-12-26T04:45:49-02:00")] - public void WhenValidDateWithTimeZoneOrOffsetPassed_ShouldConvertThatDateInUTC(string validDate) - { - //Arange - DateTime expectedDateTimeUtc = new DateTime(2016,12,26,6,45,49,DateTimeKind.Utc); - - //Act - DateTime? result = _apiTypeConverter.ToUtcDateTimeNullable(validDate); - - //Assert - Assert.AreEqual(expectedDateTimeUtc, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToEnumNullable.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToEnumNullable.cs deleted file mode 100644 index af4311f..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToEnumNullable.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Converters; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToEnumNullable - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("invalid order status", typeof(OrderStatus?))] - [TestCase("-100", typeof(OrderStatus?))] - [TestCase("345345345345345345345345345", typeof(OrderStatus?))] - [TestCase("invalid payment status", typeof(PaymentStatus?))] - [TestCase("-10", typeof(PaymentStatus?))] - [TestCase("34534343543456767", typeof(PaymentStatus?))] - [TestCase("invalid shipping status", typeof(ShippingStatus?))] - [TestCase("-17800", typeof(ShippingStatus?))] - [TestCase("546546545454546", typeof(ShippingStatus?))] - [TestCase("$%%#@@$%^^))_(!34sd", typeof(OrderStatus?))] - public void WhenInvalidEnumPassed_GivenTheEnumType_ShouldReturnNull(string invalidOrderStatus, Type type) - { - //Arange - - //Act - var result = _apiTypeConverter.ToEnumNullable(invalidOrderStatus, type); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnNull(string nullOrEmpty) - { - //Arange - - //Act - var result = _apiTypeConverter.ToEnumNullable(Arg.Is.Equal(nullOrEmpty), Arg.Is.Anything); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("Pending", typeof(OrderStatus?))] - [TestCase("Authorized", typeof(PaymentStatus?))] - [TestCase("NotYetShipped", typeof(ShippingStatus?))] - [TestCase("pending", typeof(OrderStatus?))] - [TestCase("authorized", typeof(PaymentStatus?))] - [TestCase("notyetshipped", typeof(ShippingStatus?))] - public void WhenValidEnumValuePassed_GivenTheEnumType_ShouldParseThatValueToEnum(string validEnum, Type type) - { - //Arange - var enumValueParsed = Enum.Parse(Nullable.GetUnderlyingType(type), validEnum, true); - - //Act - var result = _apiTypeConverter.ToEnumNullable(validEnum, type); - - //Assert - Assert.AreEqual(enumValueParsed, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToInt.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToInt.cs deleted file mode 100644 index 5df6155..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToInt.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Nop.Plugin.Api.Converters; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToInt - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("3ed")] - [TestCase("sd4")] - [TestCase("675435345345345345345345343456546")] - [TestCase("-675435345345345345345345343456546")] - [TestCase("$%%^%^$#^&&%#)__(^&")] - [TestCase("2015-02-12")] - [TestCase("12:45")] - public void WhenInvalidIntPassed_ShouldReturnZero(string invalidInt) - { - //Arange - - //Act - int result = _apiTypeConverter.ToInt(invalidInt); - - //Assert - Assert.AreEqual(0, result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnZero(string nullOrEmpty) - { - //Arange - - //Act - int result = _apiTypeConverter.ToInt(nullOrEmpty); - - //Assert - Assert.AreEqual(0, result); - } - - [Test] - [TestCase("3")] - [TestCase("234234")] - [TestCase("0")] - [TestCase("-44")] - [TestCase("000000005")] - public void WhenValidIntPassed_ShouldReturnThatInt(string validInt) - { - //Arange - int valid = int.Parse(validInt); - - //Act - int result = _apiTypeConverter.ToInt(validInt); - - //Assert - Assert.AreEqual(valid, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToIntNullable.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToIntNullable.cs deleted file mode 100644 index 0ca797d..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToIntNullable.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Nop.Plugin.Api.Converters; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToIntNullable - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("3ed")] - [TestCase("sd4")] - [TestCase("675435345345345345345345343456546")] - [TestCase("-675435345345345345345345343456546")] - [TestCase("$%%^%^$#^&&%#)__(^&")] - [TestCase("2015-02-12")] - [TestCase("12:45")] - public void WhenInvalidIntPassed_ShouldReturnNull(string invalidInt) - { - //Arange - - //Act - int? result = _apiTypeConverter.ToIntNullable(invalidInt); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnNull(string nullOrEmpty) - { - //Arange - - //Act - int? result = _apiTypeConverter.ToIntNullable(nullOrEmpty); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("3")] - [TestCase("234234")] - [TestCase("0")] - [TestCase("-44")] - [TestCase("000000005")] - public void WhenValidIntPassed_ShouldReturnThatInt(string validInt) - { - //Arange - int valid = int.Parse(validInt); - - //Act - int? result = _apiTypeConverter.ToIntNullable(validInt); - - //Assert - Assert.AreEqual(valid, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToListOfInts.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToListOfInts.cs deleted file mode 100644 index eda0bdd..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToListOfInts.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Plugin.Api.Converters; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToListOfInts - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("a,b,c,d")] - [TestCase(",")] - [TestCase("invalid")] - [TestCase("1 2 3 4 5")] - [TestCase("&*^&^^*()_)_-1-=")] - [TestCase("5756797879978978978978978978978978978, 234523523423423423423423423423423423423423")] - public void WhenAllPartsOfTheListAreInvalid_ShouldReturnNull(string invalidList) - { - //Arange - - //Act - IList result = _apiTypeConverter.ToListOfInts(invalidList); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnNull(string nullOrEmpty) - { - //Arange - - //Act - IList result = _apiTypeConverter.ToListOfInts(nullOrEmpty); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("1,2,3")] - [TestCase("1, 4, 7")] - [TestCase("0,-1, 7, 9 ")] - [TestCase(" 0,1 , 7, 9 ")] - public void WhenValidListPassed_ShouldReturnThatList(string validList) - { - //Arange - List expectedList = validList.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(); - - //Act - IList result = _apiTypeConverter.ToListOfInts(validList); - - //Assert - CollectionAssert.AreEqual(expectedList, result); - } - - [Test] - [TestCase("1,2, u,3")] - [TestCase("a, b, c, 1")] - [TestCase("0,-1, -, 7, 9 ")] - [TestCase("%^#^^,$,#,%,8")] - [TestCase("0")] - [TestCase("097")] - [TestCase("087, 05667, sdf")] - [TestCase("017, 345df, 05867")] - [TestCase("67856756, 05867, 76767ergdf")] - [TestCase("690, 678678678678678678678678678678678678676867867")] - public void WhenSomeOfTheItemsAreValid_ShouldReturnThatListContainingOnlyTheValidItems(string mixedList) - { - //Arange - List expectedList = new List(); - var collectionSplited = mixedList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - - int tempInt; - foreach (var item in collectionSplited) - { - if (int.TryParse(item, out tempInt)) - { - expectedList.Add(tempInt); - } - } - - //Act - IList result = _apiTypeConverter.ToListOfInts(mixedList); - - //Assert - CollectionAssert.IsNotEmpty(result); - CollectionAssert.AreEqual(expectedList, result); - } - - [Test] - [TestCase("f,d, u,3")] - [TestCase("0")] - [TestCase("097")] - [TestCase("67856756, 05ert867, 76767ergdf")] - [TestCase("690, 678678678678678678678678678678678678676867867")] - public void WhenOnlyOneOfTheItemsIsValid_ShouldReturnListContainingOnlyThatItem(string mixedList) - { - //Arange - List expectedList = new List(); - var collectionSplited = mixedList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - - int tempInt; - foreach (var item in collectionSplited) - { - if (int.TryParse(item, out tempInt)) - { - expectedList.Add(tempInt); - } - } - - //Act - IList result = _apiTypeConverter.ToListOfInts(mixedList); - - //Assert - Assert.AreEqual(1, result.Count); - CollectionAssert.IsNotEmpty(result); - CollectionAssert.AreEqual(expectedList, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToStatus.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToStatus.cs deleted file mode 100644 index f307a68..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ApiTypeConverter/ApiTypeConverterTests_ToStatus.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Nop.Plugin.Api.Converters; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ApiTypeConverter -{ - [TestFixture] - public class ApiTypeConverterTests_ToStatus - { - private IApiTypeConverter _apiTypeConverter; - - [SetUp] - public void SetUp() - { - _apiTypeConverter = new Converters.ApiTypeConverter(); - } - - [Test] - [TestCase("invalid status")] - [TestCase("publicshed")] - [TestCase("un-published")] - [TestCase("322345")] - [TestCase("%^)@*%&*@_!+=")] - [TestCase("1")] - public void WhenInvalidStatusPassed_ShouldReturnNull(string invalidStatus) - { - //Arange - - //Act - bool? result = _apiTypeConverter.ToStatus(invalidStatus); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenNullOrEmptyStringPassed_ShouldReturnNull(string nullOrEmpty) - { - //Arange - - //Act - bool? result = _apiTypeConverter.ToStatus(nullOrEmpty); - - //Assert - Assert.IsNull(result); - } - - [Test] - [TestCase("published")] - [TestCase("Published")] - [TestCase("PublisheD")] - public void WhenValidPublishedStatusPassed_ShouldReturnTrue(string validPublishedStatus) - { - //Arange - - //Act - bool? result = _apiTypeConverter.ToStatus(validPublishedStatus); - - //Assert - Assert.IsTrue(result.Value); - } - - [Test] - [TestCase("unpublished")] - [TestCase("Unpublished")] - [TestCase("UnPubLished")] - public void WhenValidUnpublishedStatusPassed_ShouldReturnFalse(string validUnpublishedStatus) - { - //Arange - - //Act - bool? result = _apiTypeConverter.ToStatus(validUnpublishedStatus); - - //Assert - Assert.IsFalse(result.Value); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/DummyObjects/SomeTestingObject.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/DummyObjects/SomeTestingObject.cs deleted file mode 100644 index 659a26c..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/DummyObjects/SomeTestingObject.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ObjectConverter.DummyObjects -{ - public class SomeTestingObject - { - public int IntProperty { get; set; } - public string StringProperty { get; set; } - public DateTime? DateTimeNullableProperty { get; set; } - public bool? BooleanNullableStatusProperty { get; set; } - public OrderStatus? OrderStatus { get; set; } - public PaymentStatus? PaymentStatus { get; set; } - public ShippingStatus? ShippingStatus { get; set; } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/ObjectConverterTests_ToObject.cs b/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/ObjectConverterTests_ToObject.cs deleted file mode 100644 index 4855a44..0000000 --- a/Nop.Plugin.Api.Tests/ConvertersTests/ObjectConverter/ObjectConverterTests_ToObject.cs +++ /dev/null @@ -1,393 +0,0 @@ -using System; -using System.Collections.Generic; -using Nop.Plugin.Api.Converters; -using Nop.Plugin.Api.Tests.ConvertersTests.ObjectConverter.DummyObjects; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ConvertersTests.ObjectConverter -{ - [TestFixture] - public class ObjectConverterTests_ToObject - { - [Test] - public void WhenCollectionIsNull_ShouldNotCallAnyOfTheApiTypeConverterMethods() - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> nullCollection = null; - - //Act - objectConverter.ToObject(nullCollection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToInt(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToIntNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToListOfInts(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToStatus(Arg.Is.Anything)); - } - - [Test] - public void WhenCollectionIsNull_ShouldReturnInstanceOfAnObjectOfTheSpecifiedType() - { - //Arange - IApiTypeConverter apiTypeConverterStub = MockRepository.GenerateStub(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterStub); - - ICollection> nullCollection = null; - - //Act - SomeTestingObject someTestingObject = objectConverter.ToObject(nullCollection); - - //Assert - Assert.IsNotNull(someTestingObject); - Assert.IsInstanceOf(typeof(SomeTestingObject), someTestingObject); - } - - [Test] - public void WhenCollectionIsNull_ShouldReturnInstanceOfAnObjectWithUnsetProperties() - { - //Arange - IApiTypeConverter apiTypeConverterStub = MockRepository.GenerateStub(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterStub); - - ICollection> nullCollection = null; - - //Act - SomeTestingObject someTestingObject = objectConverter.ToObject(nullCollection); - - //Assert - Assert.AreEqual(0, someTestingObject.IntProperty); - Assert.AreEqual(null, someTestingObject.StringProperty); - Assert.AreEqual(null, someTestingObject.DateTimeNullableProperty); - Assert.AreEqual(null, someTestingObject.BooleanNullableStatusProperty); - } - - [Test] - public void WhenCollectionIsEmpty_ShouldReturnInstanceOfAnObjectWithUnsetProperties() - { - //Arange - IApiTypeConverter apiTypeConverterStub = MockRepository.GenerateStub(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterStub); - - ICollection> emptyCollection = new List>(); - - //Act - SomeTestingObject someTestingObject = objectConverter.ToObject(emptyCollection); - - //Assert - Assert.AreEqual(0, someTestingObject.IntProperty); - Assert.AreEqual(null, someTestingObject.StringProperty); - Assert.AreEqual(null, someTestingObject.DateTimeNullableProperty); - Assert.AreEqual(null, someTestingObject.BooleanNullableStatusProperty); - } - [Test] - public void WhenCollectionIsEmpty_ShoulNotCallAnyOfTheApiTypeConverterMethods() - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> emptyCollection = new List>(); - - //Act - objectConverter.ToObject(emptyCollection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToInt(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToIntNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToListOfInts(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToStatus(Arg.Is.Anything)); - } - - [Test] - [TestCase("IntProperty")] - [TestCase("Int_Property")] - [TestCase("int_property")] - [TestCase("intproperty")] - [TestCase("inTprOperTy")] - public void WhenCollectionContainsValidIntProperty_ShouldCallTheToIntMethod(string intPropertyName) - { - //Arange - int expectedInt = 5; - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToInt(Arg.Is.Anything)).IgnoreArguments().Return(expectedInt); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(intPropertyName, expectedInt.ToString()) - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.VerifyAllExpectations(); - } - - [Test] - [TestCase("invalid int property name")] - [TestCase("34534535345345345345345345345345345345345")] - public void WhenCollectionContainsInvalidIntProperty_ShouldNotCallTheToIntMethod(string invalidIntPropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(invalidIntPropertyName, "5") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToInt(Arg.Is.Anything)); - } - - [Test] - [TestCase("StringProperty")] - [TestCase("String_Property")] - [TestCase("string_property")] - [TestCase("stringproperty")] - [TestCase("strInGprOperTy")] - public void WhenCollectionContainsValidStringProperty_ShouldSetTheObjectStringPropertyValueToTheCollectionStringPropertyValue(string stringPropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterStub = MockRepository.GenerateStub(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterStub); - - ICollection> collection = new List>() - { - new KeyValuePair(stringPropertyName, "some value") - }; - - //Act - SomeTestingObject someTestingObject = objectConverter.ToObject(collection); - - //Assert - Assert.AreEqual("some value", someTestingObject.StringProperty); - } - - [Test] - [TestCase("invalid string property name")] - public void WhenCollectionContainsInvalidStringProperty_ShouldReturnTheObjectWithItsStringPropertySetToTheDefaultValue(string invalidStringPropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterStub = MockRepository.GenerateStub(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterStub); - - ICollection> collection = new List>() - { - new KeyValuePair(invalidStringPropertyName, "some value") - }; - - //Act - SomeTestingObject someTestingObject = objectConverter.ToObject(collection); - - //Assert - Assert.IsNull(someTestingObject.StringProperty); - } - - [Test] - [TestCase("invalid string property name")] - [TestCase("StringProperty")] - [TestCase("String_Property")] - [TestCase("string_property")] - [TestCase("stringproperty")] - [TestCase("strInGprOperTy")] - public void WhenCollectionContainsValidOrInvalidStringProperty_ShouldNotCallAnyOfTheApiTypeConverterMethods(string stringProperty) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(stringProperty, "some value") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToInt(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToIntNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToListOfInts(Arg.Is.Anything)); - apiTypeConverterMock.AssertWasNotCalled(x => x.ToStatus(Arg.Is.Anything)); - } - - [Test] - [TestCase("DateTimeNullableProperty")] - [TestCase("Date_Time_Nullable_Property")] - [TestCase("date_time_nullable_property")] - [TestCase("datetimenullableproperty")] - [TestCase("dateTimeNullableProperty")] - public void WhenCollectionContainsValidDateTimeProperty_ShouldCallTheToDateTimeNullableMethod(string dateTimePropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)).IgnoreArguments().Return(DateTime.Now); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(dateTimePropertyName, "2016-12-12") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasCalled(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)); - } - - [Test] - [TestCase("invalid date time property name")] - public void WhenCollectionContainsInvalidDateTimeNullableProperty_ShouldNotCallTheDateTimeNullableMethod(string invalidDateTimeNullablePropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)).IgnoreArguments(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(invalidDateTimeNullablePropertyName, "2016-12-12") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToUtcDateTimeNullable(Arg.Is.Anything)); - } - - [Test] - [TestCase("BooleanNullableStatusProperty")] - [TestCase("BooleanNullableStatusProperty")] - [TestCase("Boolean_Nullable_Status_Property")] - [TestCase("Boolean_Nullable_Status_Property")] - [TestCase("boolean_nullable_status_property")] - [TestCase("boolean_nullable_status_property")] - [TestCase("booleannullablestatusproperty")] - [TestCase("booleannullablestatusproperty")] - [TestCase("booLeanNullabLeStaTusProperty")] - [TestCase("booLeanNullabLeStaTusProperty")] - public void WhenCollectionContainsValidBooleanStatusPropertyAndPublishedValue_ShouldCallTheToStatusMethod(string booleanStatusPropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToStatus(Arg.Is.Anything)).IgnoreArguments().Return(true); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(booleanStatusPropertyName, "some published value") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasCalled(x => x.ToStatus(Arg.Is.Anything)); - } - - [Test] - [TestCase("invalid boolean property name")] - public void WhenCollectionContainsInvalidBooleanNullableStatusProperty_ShouldNotCallTheToStatusMethod(string invalidBooleanNullableStatusPropertyName) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToStatus(Arg.Is.Anything)).IgnoreArguments(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(invalidBooleanNullableStatusPropertyName, "true") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToStatus(Arg.Is.Anything)); - } - - [Test] - [TestCase("OrderStatus")] - [TestCase("PaymentStatus")] - [TestCase("ShippingStatus")] - [TestCase("order_status")] - [TestCase("payment_status")] - [TestCase("shipping_status")] - [TestCase("orderstatus")] - [TestCase("paymentstatus")] - [TestCase("shippingstatus")] - [TestCase("OrderstaTuS")] - [TestCase("shiPpiNgStaTus")] - [TestCase("PAymeNTStatUs")] - public void WhenCollectionContainsValidNullableEnumProperty_ShouldCallTheToEnumNullableMethod(string enumNullableProperty) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToEnumNullable(Arg.Is.Anything, Arg.Is.Anything)).IgnoreArguments().Return(null); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(enumNullableProperty, "some enum value") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasCalled(x => x.ToEnumNullable(Arg.Is.Anything, Arg.Is.Anything)); - } - - [Test] - [TestCase("invalid enum property name")] - public void WhenCollectionContainsInvalidNullableEnumProperty_ShouldNotCallTheToEnumNullableMethod(string invalidEnumNullableProperty) - { - //Arange - IApiTypeConverter apiTypeConverterMock = MockRepository.GenerateMock(); - apiTypeConverterMock.Expect(x => x.ToEnumNullable(Arg.Is.Anything, Arg.Is.Anything)).IgnoreArguments(); - - IObjectConverter objectConverter = new Converters.ObjectConverter(apiTypeConverterMock); - - ICollection> collection = new List>() - { - new KeyValuePair(invalidEnumNullableProperty, "some enum value") - }; - - //Act - objectConverter.ToObject(collection); - - //Assert - apiTypeConverterMock.AssertWasNotCalled(x => x.ToEnumNullable(Arg.Is.Anything, Arg.Is.Anything)); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/Helpers/ActionResultExecutor.cs b/Nop.Plugin.Api.Tests/Helpers/ActionResultExecutor.cs deleted file mode 100644 index ed84159..0000000 --- a/Nop.Plugin.Api.Tests/Helpers/ActionResultExecutor.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Nop.Plugin.Api.Tests.Helpers -{ - using System.Net; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using Rhino.Mocks; - - public static class ActionResultExecutor - { - public static HttpStatusCode ExecuteResult(IActionResult result) - { - var actionContext = MockRepository.GenerateStub(); - actionContext.HttpContext = new DefaultHttpContext(); - - result.ExecuteResultAsync(actionContext); - var statusCode = actionContext.HttpContext.Response.StatusCode; - - return (HttpStatusCode)statusCode; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/MappingTests/CategoryMappings_Merge.cs b/Nop.Plugin.Api.Tests/MappingTests/CategoryMappings_Merge.cs deleted file mode 100644 index 4bd68ee..0000000 --- a/Nop.Plugin.Api.Tests/MappingTests/CategoryMappings_Merge.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Attributes; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.MappingExtensions; -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests.MappingTests -{ - [TestFixture] - public class CategoryMappings_Merge - { - // This attribute means that the setup method will be called only once for all tests, not before each test. - //[OneTimeSetUp] - //public void Setup() - //{ - // Maps.CreateUpdateMap(); - //} - - //[Test] - //public void WhenOnlyTheNamePropertyIsSetInDto_GivenEntityWithMultiplePropertiesSetIncludingTheName_ShouldReturnEntityWithOnlyTheNameChanged() - //{ - // var entity = new Category() - // { - // Name = "entity name", - // Description = "some description" - // }; - - // var dto = new CategoryDto() - // { - // Name = "updated name" - // }; - - // //Attributes are readonly - http://stackoverflow.com/questions/10046601/change-custom-attributes-parameter-at-runtime - // // So we are going to try to replace the attribute with new instance. - - // //****************************** - - // PropertyOverridingTypeDescriptor ctd = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(dto).GetTypeDescriptor(dto)); - - // PropertyDescriptor desriptionPorpertyDescriptor = ctd.GetProperties().Find("Description", true); - - // PropertyDescriptor pd2 = - // TypeDescriptor.CreateProperty( - // dto.GetType(), - // desriptionPorpertyDescriptor, // base property descriptor to which we want to add attributes - // // The PropertyDescriptor which we'll get will just wrap that - // // base one returning attributes we need. - // new Updated(false) - // // this method really can take as many attributes as you like, - // // not just one - // ); - - // // and then we tell our new PropertyOverridingTypeDescriptor to override that property - // ctd.OverrideProperty(pd2); - - // // then we add new descriptor provider that will return our descriptor istead of default - // TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(ctd), dto); - - // //****************************** - - // Category resultEntity = entity.Merge(dto); - - // // The name should be updated - // Assert.AreEqual(dto.Name, resultEntity.Name); - // // The description shouldn't be updated - // Assert.NotNull(entity.Description); - // Assert.AreEqual(entity.Description, resultEntity.Description); - //} - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ModelBinderTests/DummyObjects/DummyModel.cs b/Nop.Plugin.Api.Tests/ModelBinderTests/DummyObjects/DummyModel.cs deleted file mode 100644 index b7869f2..0000000 --- a/Nop.Plugin.Api.Tests/ModelBinderTests/DummyObjects/DummyModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Nop.Plugin.Api.Tests.ModelBinderTests.DummyObjects -{ - public class DummyModel - { - public string StringProperty { get; set; } - public int IntProperty { get; set; } - public int? IntNullableProperty { get; set; } - public DateTime? DateTimeNullableProperty { get; set; } - public bool? BooleanNullableStatusProperty { get; set; } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ModelBinderTests/JsonModelBinderTests_BindModel.cs b/Nop.Plugin.Api.Tests/ModelBinderTests/JsonModelBinderTests_BindModel.cs deleted file mode 100644 index c26a7da..0000000 --- a/Nop.Plugin.Api.Tests/ModelBinderTests/JsonModelBinderTests_BindModel.cs +++ /dev/null @@ -1,81 +0,0 @@ -//using System.Collections.Generic; -//using System.Net.Http; -//using System.Net.Http.Formatting; -//using System.Web.Http.Controllers; -//using System.Web.Http.Metadata; -//using System.Web.Http.ModelBinding; -//using Nop.Plugin.Api.Helpers; -//using Nop.Plugin.Api.ModelBinders; -//using NUnit.Framework; -//using Rhino.Mocks; - -//namespace Nop.Plugin.Api.Tests.ModelBinderTests -//{ -// [TestFixture] -// public class JsonModelBinderTests_BindModel -// { -// private JsonModelBinder _binder; - -// [SetUp] -// public void SetUp() -// { -// _binder = new JsonModelBinder(new JsonHelper()); -// } - -// [Test] -// public void WhenRequestDoesNotContainPayload_BindingContextShouldContainInstanceOfTheModelType() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Post, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(Dictionary), new Dictionary(), new JsonMediaTypeFormatter()); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(Dictionary), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.IsInstanceOf>(bindingContext.Model); -// } - -// [Test] -// public void WhenRequestContainsContentWithValidProperty_BindingContextShouldContainInstanceOfTheModelTypeWithItsPropertySetToTheValue() -// { -// string categoryName = "test category name"; - -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Post, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(Dictionary), -// new Dictionary() -// { -// { -// "name", -// categoryName -// } -// }, -// new JsonMediaTypeFormatter()); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(Dictionary), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.AreEqual(categoryName, ((Dictionary)bindingContext.Model)["name"]); -// } -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ModelBinderTests/ParametersModelBinderTests_BindModel.cs b/Nop.Plugin.Api.Tests/ModelBinderTests/ParametersModelBinderTests_BindModel.cs deleted file mode 100644 index 525cead..0000000 --- a/Nop.Plugin.Api.Tests/ModelBinderTests/ParametersModelBinderTests_BindModel.cs +++ /dev/null @@ -1,182 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Net.Http; -//using System.Net.Http.Formatting; -//using Nop.Plugin.Api.Converters; -//using Nop.Plugin.Api.ModelBinders; -//using Nop.Plugin.Api.Tests.ModelBinderTests.DummyObjects; -//using NUnit.Framework; -//using Rhino.Mocks; - -//namespace Nop.Plugin.Api.Tests.ModelBinderTests -//{ -// using Microsoft.AspNetCore.Mvc.Internal; -// using Microsoft.AspNetCore.Mvc.ModelBinding; -// using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; - -// [TestFixture] -// public class ParametersModelBinderTests_BindModel -// { -// private ParametersModelBinder _binder; - -// [SetUp] -// public void SetUp() -// { -// IApiTypeConverter apiTypeConverter = new ApiTypeConverter(); -// IObjectConverter objectConverter = new ObjectConverter(apiTypeConverter); -// _binder = new ParametersModelBinder(objectConverter); -// } - -// [Test] -// public void WhenRequestDoesNotContainQuery_BindingContextShouldContainInstanceOfTheModelType() -// { -// // Arrange -// var bindingContext = new DefaultModelBindingContext(); -// var modelProvider = MockRepository.GenerateStub(); -// var detailsProvider = MockRepository.GenerateStub(); -// var metaData = new DefaultModelMetadata(modelProvider, detailsProvider, new DefaultMetadataDetails()); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModelAsync(bindingContext); - -// // Assert -// Assert.IsInstanceOf(bindingContext.Model); -// } - -// [Test] -// public void WhenRequestContainsQueryWithValidIntProperty_BindingContextShouldContainInstanceOfTheModelTypeWithItsIntPropertySetToTheValue() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(DummyModel), new DummyModel(), new XmlMediaTypeFormatter()); - -// httpControllerContext.Request.Properties.Add("MS_QueryNameValuePairs", new List>() -// { -// new KeyValuePair("int_property", "5") -// }); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(DummyModel), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.AreEqual(5, ((DummyModel)bindingContext.Model).IntProperty); -// } - -// [Test] -// public void WhenRequestContainsQueryWithValidStringProperty_BindingContextShouldContainInstanceOfTheModelTypeWithItsStringPropertySetToTheValue() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(DummyModel), new DummyModel(), new XmlMediaTypeFormatter()); - -// httpControllerContext.Request.Properties.Add("MS_QueryNameValuePairs", new List>() -// { -// new KeyValuePair("string_property", "some value") -// }); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(DummyModel), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.AreEqual("some value", ((DummyModel)bindingContext.Model).StringProperty); -// } - -// [Test] -// public void WhenRequestContainsQueryWithValidDateTimeProperty_BindingContextShouldContainInstanceOfTheModelTypeWithItsDateTimePropertySetToTheValue() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(DummyModel), new DummyModel(), new XmlMediaTypeFormatter()); - -// httpControllerContext.Request.Properties.Add("MS_QueryNameValuePairs", new List>() -// { -// new KeyValuePair("date_time_nullable_property", "2016-12-12") -// }); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(DummyModel), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.AreEqual(new DateTime(2016, 12, 12), ((DummyModel)bindingContext.Model).DateTimeNullableProperty.Value); -// } - -// [Test] -// public void WhenRequestContainsQueryWithValidBooleanStatusProperty_BindingContextShouldContainInstanceOfTheModelTypeWithItBooleanStatusPropertySetToTheValue() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(DummyModel), new DummyModel(), new XmlMediaTypeFormatter()); - -// httpControllerContext.Request.Properties.Add("MS_QueryNameValuePairs", new List>() -// { -// new KeyValuePair("boolean_nullable_status_property", "published") -// }); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(DummyModel), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.AreEqual(true, ((DummyModel)bindingContext.Model).BooleanNullableStatusProperty.Value); -// } - -// [Test] -// public void BindModel_ShouldAlwaysReturnTrue() -// { -// // Arrange -// var httpControllerContext = new HttpControllerContext(); -// httpControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); -// httpControllerContext.Request.Content = new ObjectContent(typeof(DummyModel), new DummyModel(), new XmlMediaTypeFormatter()); - -// var httpActionContext = new HttpActionContext(); -// httpActionContext.ControllerContext = httpControllerContext; - -// var bindingContext = new ModelBindingContext(); -// var provider = MockRepository.GenerateStub(); -// var metaData = new ModelMetadata(provider, null, null, typeof(DummyModel), null); -// bindingContext.ModelMetadata = metaData; - -// //Act -// bool result = _binder.BindModel(httpActionContext, bindingContext); - -// // Assert -// Assert.IsTrue(result); -// } -// } -//} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/Nop.Plugin.Api.Tests.csproj b/Nop.Plugin.Api.Tests/Nop.Plugin.Api.Tests.csproj deleted file mode 100644 index 4dce13e..0000000 --- a/Nop.Plugin.Api.Tests/Nop.Plugin.Api.Tests.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - net461 - 4.0.0.0 - Nop-Templates, Ltd - Nop-Templates, Ltd - The project contains a set of classes for testing of Nop.Plugin.Api - Copyright © Nop-Templates, Ltd - Git - Nop.Plugin.Api.Tests - - - - 1.0.3.2 - - - 3.9.0 - - - 3.6.1 - - - - - - - - - - - diff --git a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithComplexTypes.cs b/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithComplexTypes.cs deleted file mode 100644 index 833ec27..0000000 --- a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithComplexTypes.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Nop.Plugin.Api.Tests.SerializersTests.DummyObjects -{ - public class DummyObjectWithComplexTypes - { - [JsonProperty("string_property")] - public string StringProperty { get; set; } - - [JsonProperty("int_property")] - public int IntProperty { get; set; } - - [JsonProperty("bool_property")] - public bool BoolProperty { get; set; } - - [JsonProperty("list_of_dummy_object_with_simple_types")] - public IList ListOfDummyObjectWithSimpleTypes { get; set; } - - [JsonProperty("dummy_object_with_simple_types")] - public DummyObjectWithSimpleTypes DummyObjectWithSimpleTypes { get; set; } - - public override bool Equals(object obj) - { - if (obj is DummyObjectWithComplexTypes) - { - var that = obj as DummyObjectWithComplexTypes; - - return that.StringProperty.Equals(StringProperty) && - that.IntProperty == IntProperty && - that.BoolProperty == BoolProperty && - that.ListOfDummyObjectWithSimpleTypes.Equals(ListOfDummyObjectWithSimpleTypes) && - that.DummyObjectWithSimpleTypes.Equals(DummyObjectWithSimpleTypes); - } - - return false; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithSimpleTypes.cs b/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithSimpleTypes.cs deleted file mode 100644 index 03d77db..0000000 --- a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/DummyObjectWithSimpleTypes.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Newtonsoft.Json; - -namespace Nop.Plugin.Api.Tests.SerializersTests.DummyObjects -{ - public class DummyObjectWithSimpleTypes - { - [JsonProperty("first_property")] - public string FirstProperty { get; set; } - - [JsonProperty("second_property")] - public string SecondProperty { get; set; } - - public override bool Equals(object obj) - { - if (obj is DummyObjectWithSimpleTypes) - { - var that = obj as DummyObjectWithSimpleTypes; - - return that.FirstProperty.Equals(FirstProperty) && that.SecondProperty.Equals(SecondProperty); - } - - return false; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithComplexTypes.cs b/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithComplexTypes.cs deleted file mode 100644 index 8b939f4..0000000 --- a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithComplexTypes.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs; - -namespace Nop.Plugin.Api.Tests.SerializersTests.DummyObjects -{ - public class SerializableDummyObjectWithComplexTypes : ISerializableObject - { - public SerializableDummyObjectWithComplexTypes() - { - Items = new List(); - } - - [JsonProperty("primary_complex_property")] - public IList Items { get; set; } - - public string GetPrimaryPropertyName() - { - return "primary_complex_property"; - } - - public Type GetPrimaryPropertyType() - { - return typeof(DummyObjectWithComplexTypes); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithSimpleTypes.cs b/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithSimpleTypes.cs deleted file mode 100644 index 46850ae..0000000 --- a/Nop.Plugin.Api.Tests/SerializersTests/DummyObjects/SerializableDummyObjectWithSimpleTypes.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs; - -namespace Nop.Plugin.Api.Tests.SerializersTests.DummyObjects -{ - public class SerializableDummyObjectWithSimpleTypes : ISerializableObject - { - public SerializableDummyObjectWithSimpleTypes() - { - Items = new List(); - } - - [JsonProperty("primary_property")] - public IList Items { get; set; } - - public string GetPrimaryPropertyName() - { - return "primary_property"; - } - - public Type GetPrimaryPropertyType() - { - return typeof (DummyObjectWithSimpleTypes); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/SerializersTests/JsonFieldsSerializerTests_Serialize.cs b/Nop.Plugin.Api.Tests/SerializersTests/JsonFieldsSerializerTests_Serialize.cs deleted file mode 100644 index a72cb6b..0000000 --- a/Nop.Plugin.Api.Tests/SerializersTests/JsonFieldsSerializerTests_Serialize.cs +++ /dev/null @@ -1,267 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using Newtonsoft.Json; -using Nop.Plugin.Api.DTOs; -using Nop.Plugin.Api.Tests.SerializersTests.DummyObjects; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.SerializersTests -{ - using Nop.Plugin.Api.JSON.Serializers; - - [TestFixture] - public class JsonFieldsSerializerTests_Serialize - { - - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenEmptyFieldsParameterPassed_ShouldSerializeEverythingFromThePassedObject(string emptyFieldsParameter) - { - //Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - var serializableObject = new SerializableDummyObjectWithSimpleTypes(); - serializableObject.Items.Add(new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property value", - SecondProperty = "second property value" - }); - - //Act - string serializedObjectJson = cut.Serialize(serializableObject, emptyFieldsParameter); - - //Assert - SerializableDummyObjectWithSimpleTypes dummySerializableObjectFromJson = - JsonConvert.DeserializeObject(serializedObjectJson); - - Assert.AreEqual(serializableObject.Items.Count, dummySerializableObjectFromJson.Items.Count); - Assert.AreEqual(serializableObject.Items[0], dummySerializableObjectFromJson.Items[0]); - Assert.AreEqual("first property value", dummySerializableObjectFromJson.Items[0].FirstProperty); - Assert.AreEqual("second property value", dummySerializableObjectFromJson.Items[0].SecondProperty); - } - - [Test] - public void WhenNullObjectToSerializePassed_ShouldThrowArgumentNullException() - { - Assert.Throws(WhenNulObjectToSearializePassed); - } - - private void WhenNulObjectToSearializePassed() - { - //Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - //Act - cut.Serialize(Arg.Is.Null, Arg.Is.Anything); - } - - [Test] - public void WhenNoValidFieldsInTheFieldsParameterPassed_ShouldReturnEmptyCollectionJson() - { - var dummySerializableObject = new SerializableDummyObjectWithSimpleTypes(); - dummySerializableObject.Items.Add(new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property value", - SecondProperty = "second property value", - }); - - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(dummySerializableObject, "not valid fields"); - - // Assert - SerializableDummyObjectWithSimpleTypes dummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(0, dummySerializableObjectFromJson.Items.Count); - } - - [Test] - public void WhenValidFieldsParameterPassed_ShouldSerializeTheseFieldsJson() - { - var dummySerializableObject = new SerializableDummyObjectWithSimpleTypes(); - dummySerializableObject.Items.Add(new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property value", - SecondProperty = "second property value", - }); - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(dummySerializableObject, "first_property"); - - // Assert - SerializableDummyObjectWithSimpleTypes dummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(1, dummySerializableObjectFromJson.Items.Count); - Assert.AreEqual("first property value", dummySerializableObjectFromJson.Items[0].FirstProperty); - } - - [Test] - public void WhenValidFieldsParameterPassed_ShouldNotSerializeOtherFieldsJson() - { - var dummySerializableObject = new SerializableDummyObjectWithSimpleTypes(); - dummySerializableObject.Items.Add(new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property value", - SecondProperty = "second property value", - }); - - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(dummySerializableObject, "first_property"); - - // Assert - SerializableDummyObjectWithSimpleTypes dummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(1, dummySerializableObjectFromJson.Items.Count); - Assert.IsNull(dummySerializableObjectFromJson.Items[0].SecondProperty); - } - - /* Complex dummy object */ - - [Test] - public void WhenValidFieldsParameterPassed_ShouldSerializeTheseFieldsJson_ComplexDummyObject() - { - var complexDummySerializableObject = new SerializableDummyObjectWithComplexTypes(); - - complexDummySerializableObject.Items.Add(new DummyObjectWithComplexTypes - { - StringProperty = "string value", - DummyObjectWithSimpleTypes = new DummyObjectWithSimpleTypes - { - FirstProperty = "first property value", - SecondProperty = "second property value" - }, - ListOfDummyObjectWithSimpleTypes = new List - { - new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property of list value", - SecondProperty = "second property of list value" - } - } - }); - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(complexDummySerializableObject, "string_property, dummy_object_with_simple_types, list_of_dummy_object_with_simple_types"); - - // Assert - SerializableDummyObjectWithComplexTypes complexDummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(1, complexDummySerializableObjectFromJson.Items.Count); - Assert.AreEqual(1, complexDummySerializableObjectFromJson.Items[0].ListOfDummyObjectWithSimpleTypes.Count); - Assert.AreEqual("string value", complexDummySerializableObjectFromJson.Items[0].StringProperty); - } - - [Test] - public void WhenSecondLevelValidFieldsParameterPassed_ShouldSerializeEmptyJson_ComplexDummyObject() - { - var complexDummySerializableObject = new SerializableDummyObjectWithComplexTypes(); - - complexDummySerializableObject.Items.Add(new DummyObjectWithComplexTypes - { - StringProperty = "string value", - DummyObjectWithSimpleTypes = new DummyObjectWithSimpleTypes - { - FirstProperty = "first property value", - SecondProperty = "second property value" - }, - ListOfDummyObjectWithSimpleTypes = new List - { - new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property of list value", - SecondProperty = "second property of list value" - } - } - }); - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(complexDummySerializableObject, "first_property"); - - // Assert - SerializableDummyObjectWithComplexTypes complexDummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(0, complexDummySerializableObjectFromJson.Items.Count); - } - - [Test] - public void WhenValidFieldsParameterPassed_ShouldSerializeTheseFieldsJson_ComplexDummyObjectEmptyList() - { - var complexDummySerializableObject = new SerializableDummyObjectWithComplexTypes(); - - complexDummySerializableObject.Items.Add(new DummyObjectWithComplexTypes - { - ListOfDummyObjectWithSimpleTypes = new List() - }); - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(complexDummySerializableObject, "list_of_dummy_object_with_simple_types"); - - // Assert - SerializableDummyObjectWithComplexTypes complexDummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(1, complexDummySerializableObjectFromJson.Items.Count); - Assert.AreEqual(0, complexDummySerializableObjectFromJson.Items[0].ListOfDummyObjectWithSimpleTypes.Count); - } - - [Test] - public void WhenInValidFieldsParameterPassed_ShouldSerializeTheseFieldsJson_ComplexDummyObject() - { - var complexDummySerializableObject = new SerializableDummyObjectWithComplexTypes(); - - complexDummySerializableObject.Items.Add(new DummyObjectWithComplexTypes - { - StringProperty = "string value", - DummyObjectWithSimpleTypes = new DummyObjectWithSimpleTypes - { - FirstProperty = "first property value", - SecondProperty = "second property value" - }, - ListOfDummyObjectWithSimpleTypes = new List - { - new DummyObjectWithSimpleTypes() - { - FirstProperty = "first property of list value", - SecondProperty = "second property of list value" - } - } - }); - - // Arange - IJsonFieldsSerializer cut = new JsonFieldsSerializer(); - - // Act - string json = cut.Serialize(complexDummySerializableObject, "invalid field"); - - // Assert - SerializableDummyObjectWithComplexTypes complexDummySerializableObjectFromJson = - JsonConvert.DeserializeObject(json); - - Assert.AreEqual(0, complexDummySerializableObjectFromJson.Items.Count); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_ProductIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_ProductIdParameter.cs deleted file mode 100644 index f6a3d79..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_ProductIdParameter.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoriesApiServiceTests_GetCategories_ProductIdParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private List _existingCategoryMappings; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2 }, - new Category() {Id = 3 }, - new Category() {Id = 1 }, - new Category() {Id = 4 }, - new Category() {Id = 5 }, - new Category() {Id = 6, Deleted = true }, - new Category() {Id = 7 } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - _existingCategoryMappings= new List() - { - new ProductCategory() { CategoryId = 1, ProductId = 2 }, - new ProductCategory() { CategoryId = 1, ProductId = 3 }, - new ProductCategory() { CategoryId = 2, ProductId = 2 }, - new ProductCategory() { CategoryId = 3, ProductId = 1 }, - new ProductCategory() { CategoryId = 4, ProductId = 4 }, - new ProductCategory() { CategoryId = 5, ProductId = 5 } - }; - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existingCategoryMappings.AsQueryable()); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidProductId_ShouldReturnOnlyTheCategoriesMappedToThisProduct() - { - // Arange - int productId = 3; - var expectedCollection = (from cat in _existigCategories - join mapping in _existingCategoryMappings on cat.Id equals mapping.CategoryId - where mapping.ProductId == productId - orderby cat.Id - select cat); - - // Act - var categories = _categoryApiService.GetCategories(productId: productId); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroProductId_ShouldReturnEmptyCollection(int productId) - { - // Act - var categories = _categoryApiService.GetCategories(productId: productId); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithProductIdThatDoesNotExistInTheMappings_ShouldReturnEmptyCollection(int productId) - { - // Arange - // Act - var categories = _categoryApiService.GetCategories(productId: productId); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_SinceIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_SinceIdParameter.cs deleted file mode 100644 index b882efa..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoriesApiServiceTests_GetCategories_SinceIdParameter.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoriesApiServiceTests_GetCategories_SinceIdParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2 }, - new Category() {Id = 3 }, - new Category() {Id = 1 }, - new Category() {Id = 4 }, - new Category() {Id = 5 }, - new Category() {Id = 6, Deleted = true }, - new Category() {Id = 7 } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidSinceId_ShouldReturnOnlyTheCategoriesAfterThisIdSortedById() - { - // Arange - int sinceId = 3; - var expectedCollection = _existigCategories.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var categories = _categoryApiService.GetCategories(sinceId: sinceId); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledZeroOrNegativeSinceId_ShouldReturnAllTheCategoriesSortedById(int sinceId) - { - // Arange - var expectedCollection = _existigCategories.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var categories = _categoryApiService.GetCategories(sinceId: sinceId); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledSinceIdOutsideOfTheCategoriesIdsRange_ShouldReturnEmptyCollection() - { - // Arange - int sinceId = int.MaxValue; - - // Act - var categories = _categoryApiService.GetCategories(sinceId: sinceId); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_CreatedParameters.cs deleted file mode 100644 index 9a1aa15..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_CreatedParameters.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_CreatedParameters - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigCategories = new List() - { - new Category() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Category() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Category() {Id = 4, CreatedOnUtc = _baseDate }, - new Category() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Category() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 7, Published = false, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeCategoriesCreatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigCategories.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted).OrderBy(x => x.Id); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categories = _categoryApiService.GetCategories(createdAtMin: createdAtMinDate); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCategoriesCount, categories.Count); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllCategoriesCreatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var categories = _categoryApiService.GetCategories(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeCategoriesCreatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigCategories.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted).OrderBy(x => x.Id); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categories = _categoryApiService.GetCategories(createdAtMax: createdAtMaxDate); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCategoriesCount, categories.Count); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllCategoriesCreatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var categories = _categoryApiService.GetCategories(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_DefaultParameters.cs deleted file mode 100644 index 3a5a98b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_DefaultParameters.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - //TODO: improve using sequence equal - [TestFixture] - public class CategoryApiServiceTests_GetCategories_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoCategoriesExist_ShouldReturnEmptyCollection() - { - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var categories = cut.GetCategories(); - - // Assert - Assert.AreEqual(0, categories.Count); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedCategoriesExist_ShouldReturnEmptyCollection() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 1, Deleted = true }); - existingCategories.Add(new Category() { Id = 2, Deleted = true }); - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var categories = cut.GetCategories(); - - // Assert - Assert.AreEqual(0, categories.Count); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedCategoriesExist_ShouldReturnThem() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 1 }); - existingCategories.Add(new Category() { Id = 2, Deleted = true }); - existingCategories.Add(new Category() { Id = 3 }); - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var categories = cut.GetCategories(); - - // Assert - Assert.AreEqual(2, categories.Count); - Assert.AreEqual(existingCategories[0].Id, categories[0].Id); - Assert.AreEqual(existingCategories[2].Id, categories[1].Id); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeCategoriesExist_ShouldReturnThemSortedById() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 2 }); - existingCategories.Add(new Category() { Id = 3 }); - existingCategories.Add(new Category() { Id = 1 }); - - var sortedIds = new List() {1,2,3}; - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var categories = cut.GetCategories(); - - // Assert - Assert.AreEqual(sortedIds[0], categories[0].Id); - Assert.AreEqual(sortedIds[1], categories[1].Id); - Assert.AreEqual(sortedIds[2], categories[2].Id); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_IdsParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_IdsParameter.cs deleted file mode 100644 index dd06e38..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_IdsParameter.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_IdsParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2}, - new Category() {Id = 3}, - new Category() {Id = 1}, - new Category() {Id = 4}, - new Category() {Id = 5}, - new Category() {Id = 6, Deleted = true}, - new Category() {Id = 7, Published = false} - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenCategoriesWithTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5 }; - - var categories = _categoryApiService.GetCategories(ids: idsCollection); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(idsCollection[0], categories[0].Id); - Assert.AreEqual(idsCollection[1], categories[1].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenCategoriesWithSomeOfTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5, 97373, 4 }; - - var categories = _categoryApiService.GetCategories(ids: idsCollection); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(idsCollection[0], categories[0].Id); - Assert.AreEqual(idsCollection[3], categories[1].Id); - Assert.AreEqual(idsCollection[1], categories[2].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenCategoriesThatDoNotMatchTheSpecifiedIds_ShouldReturnEmptyCollection() - { - var idsCollection = new List() { 2123434, 5456456, 97373, -45 }; - - var categories = _categoryApiService.GetCategories(ids: idsCollection); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenEmptyIdsCollection_ShouldReturnAllNotDeletedCategories() - { - var idsCollection = new List(); - - var categories = _categoryApiService.GetCategories(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(categories.Count, _existigCategories.Count(x => !x.Deleted)); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_LimitParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_LimitParameter.cs deleted file mode 100644 index ae0dd56..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_LimitParameter.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_LimitParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigCategories.Add(new Category() - { - Id = i + 1 - }); - } - - _existigCategories[5].Deleted = true; - _existigCategories[51].Published = false; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenCategoriesAboveTheLimit_ShouldReturnCollectionWithCountEqualToTheLimit() - { - //Arange - var expectedLimit = 5; - - //Act - var categories = _categoryApiService.GetCategories(limit: expectedLimit); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedLimit, categories.Count); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenCategoriesBellowTheLimit_ShouldReturnCollectionWithCountEqualToTheAvailableCategories() - { - //Arange - var expectedLimit = _existigCategories.Count(x => !x.Deleted); - - //Act - var categories = _categoryApiService.GetCategories(limit: expectedLimit + 10); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedLimit, categories.Count); - } - - [Test] - public void WhenCalledWithZeroLimitParameter_GivenSomeCategories_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = 0; - - //Act - var categories = _categoryApiService.GetCategories(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - public void WhenCalledWithNegativeLimitParameter_GivenSomeCategories_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = -10; - - //Act - var categories = _categoryApiService.GetCategories(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PageParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PageParameter.cs deleted file mode 100644 index d0d2214..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PageParameter.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_PageParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigCategories.Add(new Category() - { - Id = i + 1 - }); - } - - _existigCategories[5].Deleted = true; - _existigCategories[51].Published = false; - _existigCategories = _existigCategories.OrderBy(x => x.Id).ToList(); - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithPageParameter_GivenLimitedCategoriesCollection_ShouldReturnThePartOfTheCollectionThatCorrespondsToThePage() - { - //Arange - var limit = 5; - var page = 6; - var expectedCollection = new ApiList(_existigCategories.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var categories = _categoryApiService.GetCategories(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCollection.Count(), categories.Count); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithZeroPageParameter_GivenLimitedCategoriesCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = 0; - var expectedCollection = new ApiList(_existigCategories.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var categories = _categoryApiService.GetCategories(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCollection.Count(), categories.Count); - Assert.AreEqual(_existigCategories.First().Id, categories.First().Id); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithNegativePageParameter_GivenLimitedCategoriesCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = -30; - var expectedCollection = new ApiList(_existigCategories.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var categories = _categoryApiService.GetCategories(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCollection.Count(), categories.Count); - Assert.AreEqual(_existigCategories.First().Id, categories.First().Id); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithTooBigPageParameter_GivenLimitedCategoriesCollection_ShouldReturnEmptyCollection() - { - //Arange - var limit = 5; - var page = _existigCategories.Count / limit + 100; - - //Act - var categories = _categoryApiService.GetCategories(limit: limit, page: page); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PublishedStatusParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PublishedStatusParameter.cs deleted file mode 100644 index be0402b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_PublishedStatusParameter.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_PublishedStatusParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2, Published = true }, - new Category() {Id = 3, Published = true }, - new Category() {Id = 1, Published = false }, - new Category() {Id = 4, Published = true }, - new Category() {Id = 5, Published = true }, - new Category() {Id = 6, Deleted = true, Published = true }, - new Category() {Id = 7, Published = false } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenAskForOnlyThePublishedCategories_ShouldReturnOnlyThePublishedOnesSortedById() - { - // Arange - var expectedCollection = _existigCategories.Where(x => x.Published && !x.Deleted).OrderBy(x => x.Id); - - // Act - var categories = _categoryApiService.GetCategories(publishedStatus: true); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenAskForOnlyTheUnpublishedCategories_ShouldReturnOnlyTheUnpublishedOnesSortedById() - { - // Arange - var expectedCollection = _existigCategories.Where(x => !x.Published && !x.Deleted).OrderBy(x => x.Id); - - // Act - var categories = _categoryApiService.GetCategories(publishedStatus: false); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_UpdatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_UpdatedParameters.cs deleted file mode 100644 index 844f1f6..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategories/CategoryApiServiceTests_GetCategories_UpdatedParameters.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategories -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategories_UpdatedParameters - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 12); - - _existigCategories = new List() - { - new Category() {Id = 2, UpdatedOnUtc = _baseDate.AddMonths(2) }, - new Category() {Id = 3, UpdatedOnUtc = _baseDate.AddMonths(6) }, - new Category() {Id = 1, UpdatedOnUtc = _baseDate.AddMonths(7) }, - new Category() {Id = 4, UpdatedOnUtc = _baseDate }, - new Category() {Id = 5, UpdatedOnUtc = _baseDate.AddMonths(3) }, - new Category() {Id = 6, Deleted = true, UpdatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 7, Published = false, UpdatedOnUtc = _baseDate.AddMonths(4) } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenSomeCategoriesUpdatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = _existigCategories.Where(x => x.UpdatedOnUtc > updatedAtMinDate && !x.Deleted).OrderBy(x => x.Id); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categories = _categoryApiService.GetCategories(updatedAtMin: updatedAtMinDate); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCategoriesCount, categories.Count); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenAllCategoriesUpdatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(7); - - // Act - var categories = _categoryApiService.GetCategories(updatedAtMin: updatedAtMinDate); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenSomeCategoriesUpdatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigCategories.Where(x => x.UpdatedOnUtc < updatedAtMaxDate && !x.Deleted).OrderBy(x => x.Id); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categories = _categoryApiService.GetCategories(updatedAtMax: updatedAtMaxDate); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedCategoriesCount, categories.Count); - Assert.IsTrue(categories.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenAllCategoriesUpdatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var categories = _categoryApiService.GetCategories(updatedAtMax: updatedAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_CreatedParameters.cs deleted file mode 100644 index 3884a73..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_CreatedParameters.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoriesCount_CreatedParameters - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigCategories = new List() - { - new Category() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Category() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Category() {Id = 4, CreatedOnUtc = _baseDate }, - new Category() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Category() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 7, Published = false, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeCategoriesCreatedAfterThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigCategories.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(expectedCategoriesCount, categoriesCount); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllCategoriesCreatedBeforeThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeCategoriesCreatedBeforeThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigCategories.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(expectedCategoriesCount, categoriesCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllCategoriesCreatedAfterThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_DefaultParameters.cs deleted file mode 100644 index 13b5f5f..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_DefaultParameters.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoriesCount_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoCategoriesExist_ShouldReturnZero() - { - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var categoriesCount = cut.GetCategoriesCount(); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedCategoriesExist_ShouldReturnZero() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 1, Deleted = true }); - existingCategories.Add(new Category() { Id = 2, Deleted = true }); - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var countResult = cut.GetCategoriesCount(); - - // Assert - Assert.AreEqual(0, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedCategoriesExist_ShouldReturnTheirCount() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 1 }); - existingCategories.Add(new Category() { Id = 2, Deleted = true }); - existingCategories.Add(new Category() { Id = 3 }); - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var countResult = cut.GetCategoriesCount(); - - // Assert - Assert.AreEqual(2, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeCategoriesExist_ShouldReturnTheirCount() - { - var existingCategories = new List(); - existingCategories.Add(new Category() { Id = 2, Published = false }); - existingCategories.Add(new Category() { Id = 3 }); - existingCategories.Add(new Category() { Id = 1 }); - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(existingCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var countResult = cut.GetCategoriesCount(); - - // Assert - Assert.AreEqual(existingCategories.Count, countResult); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_ProductIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_ProductIdParameter.cs deleted file mode 100644 index 310fb01..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_ProductIdParameter.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoriesCount_ProductIdParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private List _existingCategoryMappings; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2 }, - new Category() {Id = 3 }, - new Category() {Id = 1 }, - new Category() {Id = 4 }, - new Category() {Id = 5 }, - new Category() {Id = 6, Deleted = true }, - new Category() {Id = 7 } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - _existingCategoryMappings= new List() - { - new ProductCategory() { CategoryId = 1, ProductId = 2 }, - new ProductCategory() { CategoryId = 1, ProductId = 3 }, - new ProductCategory() { CategoryId = 2, ProductId = 2 }, - new ProductCategory() { CategoryId = 3, ProductId = 1 }, - new ProductCategory() { CategoryId = 4, ProductId = 4 }, - new ProductCategory() { CategoryId = 5, ProductId = 5 } - }; - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existingCategoryMappings.AsQueryable()); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidProductId_ShouldReturnOnlyTheCountOfTheCategoriesMappedToThisProduct() - { - // Arange - int productId = 3; - var expectedCollectionCount = (from cat in _existigCategories - join mapping in _existingCategoryMappings on cat.Id equals mapping.CategoryId - where mapping.ProductId == productId - orderby cat.Id - select cat).Count(); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(productId: productId); - - // Assert - Assert.AreEqual(expectedCollectionCount, categoriesCount); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroProductId_ShouldReturnZero(int productId) - { - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(productId: productId); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithProductIdThatDoesNotExistInTheMappings_ShouldReturnZero(int productId) - { - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(productId: productId); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_PublishedStatusParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_PublishedStatusParameter.cs deleted file mode 100644 index 58287fb..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_PublishedStatusParameter.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoriesCount_PublishedStatusParameter - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - - [SetUp] - public void Setup() - { - _existigCategories = new List() - { - new Category() {Id = 2, Published = true }, - new Category() {Id = 3, Published = true }, - new Category() {Id = 1, Published = false }, - new Category() {Id = 4, Published = true }, - new Category() {Id = 5, Published = true }, - new Category() {Id = 6, Deleted = true, Published = true }, - new Category() {Id = 7, Published = false } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenAskForOnlyThePublishedCategories_ShouldReturnOnlyThePublishedCategoriesCount() - { - // Arange - var expectedCategoriesCount = _existigCategories.Count(x => x.Published && !x.Deleted); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(publishedStatus: true); - - // Assert - Assert.AreEqual(expectedCategoriesCount, categoriesCount); - } - - [Test] - public void WhenAskForOnlyTheUnpublishedCategories_ShouldReturnOnlyTheUnpublishedCategoriesCount() - { - // Arange - var expectedCollectionCount = _existigCategories.Count(x => !x.Published && !x.Deleted); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(publishedStatus: false); - - // Assert - Assert.AreEqual(expectedCollectionCount, categoriesCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_UpdatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_UpdatedParameters.cs deleted file mode 100644 index 410470b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoriesCount/CategoryApiServiceTests_GetCategoriesCount_UpdatedParameters.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoriesCount_UpdatedParameters - { - private ICategoryApiService _categoryApiService; - private List _existigCategories; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 12); - - _existigCategories = new List() - { - new Category() {Id = 2, UpdatedOnUtc = _baseDate.AddMonths(2) }, - new Category() {Id = 3, UpdatedOnUtc = _baseDate.AddMonths(6) }, - new Category() {Id = 1, UpdatedOnUtc = _baseDate.AddMonths(7) }, - new Category() {Id = 4, UpdatedOnUtc = _baseDate }, - new Category() {Id = 5, UpdatedOnUtc = _baseDate.AddMonths(3) }, - new Category() {Id = 6, Deleted = true, UpdatedOnUtc = _baseDate.AddMonths(10) }, - new Category() {Id = 7, Published = false, UpdatedOnUtc = _baseDate.AddMonths(4) } - }; - - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.TableNoTracking).Return(_existigCategories.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _categoryApiService = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenSomeCategoriesUpdatedAfterThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = _existigCategories.Where(x => x.UpdatedOnUtc > updatedAtMinDate && !x.Deleted); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(updatedAtMin: updatedAtMinDate); - - // Assert - Assert.AreEqual(expectedCategoriesCount, categoriesCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenAllCategoriesUpdatedBeforeThatDate_ShouldReturnZero() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(7); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(updatedAtMin: updatedAtMinDate); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenSomeCategoriesUpdatedBeforeThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigCategories.Where(x => x.UpdatedOnUtc < updatedAtMaxDate && !x.Deleted); - var expectedCategoriesCount = expectedCollection.Count(); - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(updatedAtMax: updatedAtMaxDate); - - // Assert - Assert.AreEqual(expectedCategoriesCount, categoriesCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenAllCategoriesUpdatedAfterThatDate_ShouldReturnZero() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var categoriesCount = _categoryApiService.GetCategoriesCount(updatedAtMax: updatedAtMaxDate); - - // Assert - Assert.AreEqual(0, categoriesCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoryById/CategoryApiServiceTests_GetCategoryById.cs b/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoryById/CategoryApiServiceTests_GetCategoryById.cs deleted file mode 100644 index 4f7e413..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Categories/GetCategoryById/CategoryApiServiceTests_GetCategoryById.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoryById -{ - using Nop.Services.Stores; - - [TestFixture] - public class CategoryApiServiceTests_GetCategoryById - { - [Test] - public void WhenNullIsReturnedByTheRepository_ShouldReturnNull() - { - int categoryId = 3; - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - categoryRepo.Stub(x => x.Table).Return((new List()).AsQueryable()); - categoryRepo.Stub(x => x.GetById(categoryId)).Return(null); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var result = cut.GetCategoryById(categoryId); - - // Assert - Assert.IsNull(result); - } - - [Test] - [TestCase(-2)] - [TestCase(0)] - public void WhenNegativeOrZeroCategoryIdPassed_ShouldReturnNull(int negativeOrZeroCategoryId) - { - // Aranges - var categoryRepoStub = MockRepository.GenerateStub>(); - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepoStub, productCategoryRepo, storeMappingService); - var result = cut.GetCategoryById(negativeOrZeroCategoryId); - - // Assert - Assert.IsNull(result); - } - - [Test] - public void WhenCategoryIsReturnedByTheRepository_ShouldReturnTheSameCategory() - { - int categoryId = 3; - Category category = new Category() { Id = 3, Name = "some name" }; - - // Arange - var categoryRepo = MockRepository.GenerateStub>(); - - var list = new List(); - list.Add(category); - - categoryRepo.Stub(x => x.Table).Return(list.AsQueryable()); - - categoryRepo.Stub(x => x.GetById(categoryId)).Return(category); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new CategoryApiService(categoryRepo, productCategoryRepo, storeMappingService); - var result = cut.GetCategoryById(categoryId); - - // Assert - Assert.AreSame(category, result); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ServicesTests/CountryApiServiceTests.cs b/Nop.Plugin.Api.Tests/ServicesTests/CountryApiServiceTests.cs deleted file mode 100644 index 682f87a..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/CountryApiServiceTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Directory; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests -{ - //[TestFixture] - //public class CountryApiServiceTests - //{ - // private ICountryApiService _countryApiService; - - // [SetUp] - // public new void SetUp() - // { - // var countryRepositoryStub = MockRepository.GenerateStub>(); - - // countryRepositoryStub.Stub(x => x.Table).Return((new List() - // { - - // new Country() - // { - // Name = "test country 1" - // }, - // new Country() - // { - // Name = "test country 2" - // } - - // }).AsQueryable()); - - // _countryApiService = new CountryApiService(countryRepositoryStub); - // } - - // [Test] - // public void Get_country_by_existing_name() - // { - // var countryResult = _countryApiService.GetCountryByName("test country 1"); - - // Assert.IsNotNull(countryResult); - // Assert.AreEqual("test country 1", countryResult.Name); - // } - - // [Test] - // public void Get_country_by_non_existing_name() - // { - // var countryResult = _countryApiService.GetCountryByName("non existing country name"); - - // Assert.IsNull(countryResult); - // } - //} -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Customers/CustomerApiServiceTests.cs b/Nop.Plugin.Api.Tests/ServicesTests/Customers/CustomerApiServiceTests.cs deleted file mode 100644 index 14e27f7..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Customers/CustomerApiServiceTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using AutoMapper; -using Nop.Core.Data; -using Nop.Core.Domain.Common; -using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Customers -{ - // Possible tests - // - - //[TestFixture] - //public class CustomerApiServiceTests - //{ - // private ICustomerApiService _customerApiService; - - // [SetUp] - // public new void SetUp() - // { - // var customerRepositoryStub = MockRepository.GenerateStub>(); - // var genericAttributeRepositoryStub = MockRepository.GenerateStub>(); - - // customerRepositoryStub.Stub(x => x.Table).Return((new List() - // { - // new Customer() - // { - // Id = 1, - // Email = "test@customer1.com" - // }, - // new Customer() - // { - // Id = 2, - // Email = "test@customer2.com" - // } - - // }).AsQueryable()); - - // genericAttributeRepositoryStub.Stub(x => x.Table).Return((new List() - // { - // new GenericAttribute() - // { - // Id = 1, - // KeyGroup = "Customer", - // Key = "FirstName", - // Value = "first name 1", - // EntityId = 1 - // }, - // new GenericAttribute() - // { - // Id = 2, - // KeyGroup = "Customer", - // Key = "LastName", - // Value = "last name 1", - // EntityId = 1 - // }, - - // new GenericAttribute() - // { - // Id = 3, - // KeyGroup = "Customer", - // Key = "FirstName", - // Value = "first name 2", - // EntityId = 2 - // }, - // new GenericAttribute() - // { - // Id = 3, - // KeyGroup = "Customer", - // Key = "LastName", - // Value = "last name 2", - // EntityId = 2 - // } - - // }).AsQueryable()); - - // _customerApiService = new CustomerApiService(customerRepositoryStub, genericAttributeRepositoryStub); - - // // Needed because the tests don't invoke the dependency register and the type maps are never registered. - // Mapper.CreateMap(); - // } - - // [Test] - // public void Get_customers_call_with_default_parameters() - // { - // var customersResult = _customerApiService.GetCustomersDtos(); - - // Assert.IsNotNull(customersResult); - // Assert.IsNotEmpty(customersResult); - // Assert.AreEqual(2, customersResult.Count); - // Assert.AreEqual("test@customer1.com", customersResult[0].Email); - // Assert.AreEqual("test@customer2.com", customersResult[1].Email); - // } - - // [Test] - // public void Get_customers_limit_set_to_1() - // { - // var customersResult = _customerApiService.GetCustomersDtos(limit: 1); - - // Assert.IsNotNull(customersResult); - // Assert.IsNotEmpty(customersResult); - // Assert.AreEqual(1, customersResult.Count); - // Assert.AreEqual("test@customer1.com", customersResult[0].Email); - // } - //} -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrderById/OrderApiServiceTests_GetOrderById.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrderById/OrderApiServiceTests_GetOrderById.cs deleted file mode 100644 index 847cc93..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrderById/OrderApiServiceTests_GetOrderById.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrderById -{ - [TestFixture] - public class OrderApiServiceTests_GetOrderById - { - [Test] - public void WhenNullIsReturnedByTheRepository_ShouldReturnNull() - { - int orderId = 3; - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.Table).Return((new List()).AsQueryable()); - orderRepo.Stub(x => x.GetById(orderId)).Return(null); - - // Act - var cut = new OrderApiService(orderRepo); - var result = cut.GetOrderById(orderId); - - // Assert - Assert.IsNull(result); - } - - [Test] - [TestCase(-2)] - [TestCase(0)] - public void WhenNegativeOrZeroOrderIdPassed_ShouldReturnNull(int negativeOrZeroOrderId) - { - // Aranges - var orderRepoStub = MockRepository.GenerateStub>(); - - // Act - var cut = new OrderApiService(orderRepoStub); - var result = cut.GetOrderById(negativeOrZeroOrderId); - - // Assert - Assert.IsNull(result); - } - - [Test] - public void WhenOrderIsReturnedByTheRepository_ShouldReturnTheSameOrder() - { - int orderId = 3; - var order = new Order() { Id = 3 }; - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - - var list = new List(); - list.Add(order); - - orderRepo.Stub(x => x.Table).Return(list.AsQueryable()); - orderRepo.Stub(x => x.GetById(orderId)).Return(order); - - // Act - var cut = new OrderApiService(orderRepo); - var result = cut.GetOrderById(orderId); - - // Assert - Assert.AreSame(order, result); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CreatedParameters.cs deleted file mode 100644 index c2e4e31..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CreatedParameters.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_CreatedParameters - { - private IOrderApiService _orderApiService; - private List _existigOrders; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigOrders = new List() - { - new Order() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Order() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Order() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Order() {Id = 4, CreatedOnUtc = _baseDate }, - new Order() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Order() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Order() {Id = 7, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeOrdersCreatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - - var expectedCollection = - _existigOrders.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted).OrderBy(x => x.Id); - - var expectedOrdersCount = expectedCollection.Count(); - - // Act - var orders = _orderApiService.GetOrders(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedOrdersCount, orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllOrdersCreatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var orders = _orderApiService.GetOrders(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeOrdersCreatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigOrders.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted).OrderBy(x => x.Id); - var expectedOrdersCount = expectedCollection.Count(); - - // Act - var orders = _orderApiService.GetOrders(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedOrdersCount, orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllOrdersCreatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var orders = _orderApiService.GetOrders(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CustomerIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CustomerIdParameter.cs deleted file mode 100644 index 942ea5f..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_CustomerIdParameter.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_CustomerIdParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2, CustomerId = 1}, - new Order() {Id = 3, CustomerId = 1}, - new Order() {Id = 1, CustomerId = 2}, - new Order() {Id = 4, CustomerId = 1}, - new Order() {Id = 5, CustomerId = 2}, - new Order() {Id = 6, CustomerId = 1, Deleted = true}, - new Order() {Id = 7, CustomerId = 2} - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(productRepo); - } - - [Test] - public void WhenCalledWithValidCustomerId_ShouldReturnOnlyTheOrdersForThisCustomer() - { - // Arange - int customerId = 1; - var expectedCollection = - _existigOrders.Where(x => x.CustomerId == customerId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(customerId: customerId); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroCustomerId_ShouldReturnEmptyCollection(int customerId) - { - // Act - var orders = _orderApiService.GetOrders(customerId: customerId); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithCustomerIdThatDoesNotExistInTheMappings_ShouldReturnEmptyCollection(int customerId) - { - // Act - var orders = _orderApiService.GetOrders(customerId: customerId); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_DefaultParameters.cs deleted file mode 100644 index 70e4c77..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_DefaultParameters.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoOrdersExist_ShouldReturnEmptyCollection() - { - // Arange - var ordersRepo = MockRepository.GenerateStub>(); - ordersRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - // Act - var cut = new OrderApiService(ordersRepo); - var orders = cut.GetOrders(); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedOrdersExist_ShouldReturnEmptyCollection() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 1, Deleted = true }); - existingOrders.Add(new Order() { Id = 2, Deleted = true }); - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(orderRepo); - var orders = cut.GetOrders(); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedOrdersExist_ShouldReturnThemSortedById() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 1 }); - existingOrders.Add(new Order() { Id = 2, Deleted = true }); - existingOrders.Add(new Order() { Id = 3 }); - - var expectedCollection = existingOrders.Where(x => !x.Deleted).OrderBy(x => x.Id); - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(orderRepo); - var orders = cut.GetOrders(); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeOrdersExist_ShouldReturnThemSortedById() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 2 }); - existingOrders.Add(new Order() { Id = 3 }); - existingOrders.Add(new Order() { Id = 1 }); - - var expectedCollection = existingOrders.Where(x => !x.Deleted).OrderBy(x => x.Id); - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(orderRepo); - var orders = cut.GetOrders(); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_IdsParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_IdsParameter.cs deleted file mode 100644 index 4e8059c..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_IdsParameter.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_IdsParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2}, - new Order() {Id = 3}, - new Order() {Id = 1}, - new Order() {Id = 4}, - new Order() {Id = 5}, - new Order() {Id = 6, Deleted = true}, - new Order() {Id = 7} - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenOrdersWithTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5 }; - - var orders = _orderApiService.GetOrders(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(idsCollection[0], orders[0].Id); - Assert.AreEqual(idsCollection[1], orders[1].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenOrdersWithSomeOfTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5, 97373, 4 }; - - var orders = _orderApiService.GetOrders(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(idsCollection[0], orders[0].Id); - Assert.AreEqual(idsCollection[3], orders[1].Id); - Assert.AreEqual(idsCollection[1], orders[2].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenOrdersThatDoNotMatchTheSpecifiedIds_ShouldReturnEmptyCollection() - { - var idsCollection = new List() { 2123434, 5456456, 97373, -45 }; - - var orders = _orderApiService.GetOrders(ids: idsCollection); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenEmptyIdsCollection_ShouldReturnAllNotDeletedOrders() - { - var idsCollection = new List(); - - var orders = _orderApiService.GetOrders(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(orders.Count, _existigOrders.Count(x => !x.Deleted)); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_LimitParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_LimitParameter.cs deleted file mode 100644 index c39be18..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_LimitParameter.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_LimitParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigOrders.Add(new Order() - { - Id = i + 1 - }); - } - - _existigOrders[5].Deleted = true; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenOrdersAboveTheLimit_ShouldReturnCollectionWithCountEqualToTheLimit() - { - //Arange - var expectedLimit = 5; - - //Act - var orders = _orderApiService.GetOrders(limit: expectedLimit); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedLimit, orders.Count); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenOrdersBellowTheLimit_ShouldReturnCollectionWithCountEqualToTheAvailableOrders() - { - //Arange - var expectedLimit = _existigOrders.Count(x => !x.Deleted); - - //Act - var orders = _orderApiService.GetOrders(limit: expectedLimit + 10); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedLimit, orders.Count); - } - - [Test] - public void WhenCalledWithZeroLimitParameter_GivenSomeOrders_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = 0; - - //Act - var orders = _orderApiService.GetOrders(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(orders); - } - - [Test] - public void WhenCalledWithNegativeLimitParameter_GivenSomeOrders_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = -10; - - //Act - var orders = _orderApiService.GetOrders(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_PageParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_PageParameter.cs deleted file mode 100644 index 311c9ca..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_PageParameter.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_PageParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigOrders.Add(new Order() - { - Id = i + 1 - }); - } - - _existigOrders[5].Deleted = true; - _existigOrders = _existigOrders.OrderBy(x => x.Id).ToList(); - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithPageParameter_GivenLimitedOrdersCollection_ShouldReturnThePartOfTheCollectionThatCorrespondsToThePage() - { - //Arange - var limit = 5; - var page = 6; - var expectedCollection = new ApiList(_existigOrders.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var orders = _orderApiService.GetOrders(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithZeroPageParameter_GivenLimitedOrdersCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = 0; - var expectedCollection = new ApiList(_existigOrders.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var orders = _orderApiService.GetOrders(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.AreEqual(_existigOrders.First().Id, orders.First().Id); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithNegativePageParameter_GivenLimitedOrdersCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = -30; - var expectedCollection = new ApiList(_existigOrders.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var orders = _orderApiService.GetOrders(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.AreEqual(_existigOrders.First().Id, orders.First().Id); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithTooBigPageParameter_GivenLimitedOrdersCollection_ShouldReturnEmptyCollection() - { - //Arange - var limit = 5; - var page = _existigOrders.Count / limit + 100; - - //Act - var orders = _orderApiService.GetOrders(limit: limit, page: page); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_SinceIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_SinceIdParameter.cs deleted file mode 100644 index 69dc292..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_SinceIdParameter.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_SinceIdParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2 }, - new Order() {Id = 3 }, - new Order() {Id = 1 }, - new Order() {Id = 4 }, - new Order() {Id = 5 }, - new Order() {Id = 6, Deleted = true }, - new Order() {Id = 7 } - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithValidSinceId_ShouldReturnOnlyTheOrdersAfterThisIdSortedById() - { - // Arange - int sinceId = 3; - var expectedCollection = _existigOrders.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(sinceId: sinceId); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledZeroOrNegativeSinceId_ShouldReturnAllTheOrdersSortedById(int sinceId) - { - // Arange - var expectedCollection = _existigOrders.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(sinceId: sinceId); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledSinceIdOutsideOfTheOrdersIdsRange_ShouldReturnEmptyCollection() - { - // Arange - int sinceId = int.MaxValue; - - // Act - var orders = _orderApiService.GetOrders(sinceId: sinceId); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_StatusesParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_StatusesParameters.cs deleted file mode 100644 index 5b7518a..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrders/OrderApiServiceTests_GetOrders_StatusesParameters.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrders -{ - [TestFixture] - public class OrderApiServiceTests_GetOrders_StatusesParameters - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2, OrderStatus = OrderStatus.Complete }, - new Order() {Id = 3, PaymentStatus = PaymentStatus.Paid }, - new Order() {Id = 1, ShippingStatus = ShippingStatus.Delivered }, - new Order() {Id = 4, OrderStatus = OrderStatus.Cancelled, PaymentStatus = PaymentStatus.Pending }, - new Order() {Id = 5, ShippingStatus = ShippingStatus.NotYetShipped, PaymentStatus = PaymentStatus.Paid }, - new Order() {Id = 6, OrderStatus = OrderStatus.Complete, ShippingStatus = ShippingStatus.ShippingNotRequired }, - new Order() {Id = 7, OrderStatus = OrderStatus.Cancelled, PaymentStatus = PaymentStatus.Refunded, ShippingStatus = ShippingStatus.NotYetShipped } - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - [TestCase(OrderStatus.Complete)] - [TestCase(OrderStatus.Cancelled)] - public void WhenCalledWithSomeOrderStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheOrdersHavingThisStatusOrderedById(OrderStatus orderStatus) - { - // Arange - var expectedCollection = _existigOrders.Where(x => x.OrderStatus == orderStatus).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(status: orderStatus); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(PaymentStatus.Paid)] - [TestCase(PaymentStatus.Refunded)] - public void WhenCalledWithSomePaymentStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheOrdersHavingThisStatusOrderedById(PaymentStatus paymentStatus) - { - // Arange - var expectedCollection = _existigOrders.Where(x => x.PaymentStatus == paymentStatus).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(paymentStatus: paymentStatus); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(ShippingStatus.Delivered)] - [TestCase(ShippingStatus.ShippingNotRequired)] - public void WhenCalledWithSomeShippingStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheOrdersHavingThisStatusOrderedById(ShippingStatus shippingStatus) - { - // Arange - var expectedCollection = _existigOrders.Where(x => x.ShippingStatus == shippingStatus).OrderBy(x => x.Id); - - // Act - var orders = _orderApiService.GetOrders(shippingStatus: shippingStatus); - - // Assert - CollectionAssert.IsNotEmpty(orders); - Assert.AreEqual(expectedCollection.Count(), orders.Count); - Assert.IsTrue(orders.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithStatus_GivenOrdersCollectionThatDoNotHaveThisStatus_ShouldReturnEmptyCollection() - { - // Arange - var orderStatus = OrderStatus.Processing; - var paymentStatus = PaymentStatus.PartiallyRefunded; - var shippingStatus = ShippingStatus.Shipped; - - // Act - var orders = new List(); - - List ordersByOrderStatus = _orderApiService.GetOrders(status: orderStatus).ToList(); - List ordersByPaymentStatus = _orderApiService.GetOrders(paymentStatus: paymentStatus).ToList(); - List ordersByShippingStatus = _orderApiService.GetOrders(shippingStatus: shippingStatus).ToList(); - - orders.AddRange(ordersByOrderStatus); - orders.AddRange(ordersByPaymentStatus); - orders.AddRange(ordersByShippingStatus); - - // Assert - CollectionAssert.IsEmpty(orders); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersByCustomerId/OrderApiServiceTests_GetOrdersByCustomerId.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersByCustomerId/OrderApiServiceTests_GetOrdersByCustomerId.cs deleted file mode 100644 index 89f0131..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersByCustomerId/OrderApiServiceTests_GetOrdersByCustomerId.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrdersByCustomerId -{ - [TestFixture] - public class OrderApiServiceTests_GetOrdersByCustomerId - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2, CustomerId = 1}, - new Order() {Id = 3, CustomerId = 2}, - new Order() {Id = 1, CustomerId = 2}, - new Order() {Id = 4, CustomerId = 1}, - new Order() {Id = 5, CustomerId = 1}, - new Order() {Id = 6, CustomerId = 2}, - new Order() {Id = 7, CustomerId = 1, Deleted = true} - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - [TestCase(0)] - [TestCase(-30)] - public void WhenZeroOrNegativeCustomerIdPassed_ShouldReturnEmptyCollection(int negativeOrZeroCustomerId) - { - // Act - var result = _orderApiService.GetOrdersByCustomerId(negativeOrZeroCustomerId); - - // Assert - CollectionAssert.IsEmpty(result); - } - - [Test] - [TestCase(34988934)] - [TestCase(98472)] - public void WhenNonExistingCustomerIdPassed_ShouldReturnEmptyCollection(int nonExistingCustomerId) - { - // Act - var result = _orderApiService.GetOrdersByCustomerId(nonExistingCustomerId); - - // Assert - CollectionAssert.IsEmpty(result); - } - - [Test] - [TestCase(1)] - [TestCase(2)] - public void WhenExistingCustomerIdPassed_ShouldReturnTheNonDeletedOrdersOrderedById(int existingCustomerId) - { - // Arange - var expectedCollection = _existigOrders.Where(x => x.CustomerId == existingCustomerId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var result = _orderApiService.GetOrdersByCustomerId(existingCustomerId); - - // Assert - CollectionAssert.IsNotEmpty(result); - Assert.IsTrue(result.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CreatedParameters.cs deleted file mode 100644 index f6e6917..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CreatedParameters.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrdersCount -{ - [TestFixture] - public class OrderApiServiceTests_GetOrdersCount_CreatedParameters - { - private IOrderApiService _orderApiService; - private List _existigOrders; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigOrders = new List() - { - new Order() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Order() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Order() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Order() {Id = 4, CreatedOnUtc = _baseDate }, - new Order() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Order() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Order() {Id = 7, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeOrdersCreatedAfterThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigOrders.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted); - var expectedOrdersCount = expectedCollection.Count(); - - // Act - var ordersCount = _orderApiService.GetOrdersCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(expectedOrdersCount, ordersCount); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllOrdersCreatedBeforeThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var ordersCount = _orderApiService.GetOrdersCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(0, ordersCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeOrdersCreatedBeforeThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigOrders.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted); - var expectedOrdersCount = expectedCollection.Count(); - - // Act - var ordersCount = _orderApiService.GetOrdersCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(expectedOrdersCount, ordersCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllOrdersCreatedAfterThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var ordersCount = _orderApiService.GetOrdersCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(0, ordersCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CustomerIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CustomerIdParameter.cs deleted file mode 100644 index b26197d..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_CustomerIdParameter.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrdersCount -{ - [TestFixture] - public class OrderApiServiceTests_GetOrdersCount_CustomerIdParameter - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2, CustomerId = 1}, - new Order() {Id = 3, CustomerId = 2}, - new Order() {Id = 1, CustomerId = 2}, - new Order() {Id = 4, CustomerId = 1}, - new Order() {Id = 5, CustomerId = 1}, - new Order() {Id = 6, CustomerId = 2}, - new Order() {Id = 7, CustomerId = 1, Deleted = true} - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - public void WhenCalledWithValidCustomerId_ShouldReturnTheCountOfTheOrdersForThisCustomer() - { - // Arange - int customerId = 1; - var expectedCollectionCount = _existigOrders.Count(x => x.CustomerId == customerId && !x.Deleted); - - // Act - var productsCount = _orderApiService.GetOrdersCount(customerId: customerId); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroCustomerId_ShouldReturnZero(int customerId) - { - // Act - var ordersCount = _orderApiService.GetOrdersCount(customerId: customerId); - - // Assert - Assert.AreEqual(0, ordersCount); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithCustomerIdThatDoesNotExistInTheMappings_ShouldReturnZero(int customerId) - { - // Act - var ordersCount = _orderApiService.GetOrdersCount(customerId: customerId); - - // Assert - Assert.AreEqual(0, ordersCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_DefaultParameters.cs deleted file mode 100644 index 9947a7b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_DefaultParameters.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrdersCount -{ - [TestFixture] - public class OrderApiServiceTests_GetOrdersCount_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoOrdersExist_ShouldReturnZero() - { - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - // Act - var cut = new OrderApiService(orderRepo); - var ordersCount = cut.GetOrdersCount(); - - // Assert - Assert.AreEqual(0, ordersCount); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedOrdersExist_ShouldReturnZero() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 1, Deleted = true }); - existingOrders.Add(new Order() { Id = 2, Deleted = true }); - - // Arange - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(orderRepo); - var countResult = cut.GetOrdersCount(); - - // Assert - Assert.AreEqual(0, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedOrderExist_ShouldReturnTheirCount() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 1 }); - existingOrders.Add(new Order() { Id = 2, Deleted = true }); - existingOrders.Add(new Order() { Id = 3 }); - - // Arange - var ordersRepo = MockRepository.GenerateStub>(); - ordersRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(ordersRepo); - var countResult = cut.GetOrdersCount(); - - // Assert - Assert.AreEqual(2, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeOrdersExist_ShouldReturnTheirCount() - { - var existingOrders = new List(); - existingOrders.Add(new Order() { Id = 2 }); - existingOrders.Add(new Order() { Id = 3 }); - existingOrders.Add(new Order() { Id = 1 }); - - // Arange - var ordersRepo = MockRepository.GenerateStub>(); - ordersRepo.Stub(x => x.TableNoTracking).Return(existingOrders.AsQueryable()); - - // Act - var cut = new OrderApiService(ordersRepo); - var countResult = cut.GetOrdersCount(); - - // Assert - Assert.AreEqual(existingOrders.Count, countResult); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_StatusesParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_StatusesParameters.cs deleted file mode 100644 index 6bc7881..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Orders/GetOrdersCount/OrderApiServiceTests_GetOrdersCount_StatusesParameters.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Orders.GetOrdersCount -{ - [TestFixture] - public class OrderApiServiceTests_GetOrdersCount_StatusesParameters - { - private IOrderApiService _orderApiService; - private List _existigOrders; - - [SetUp] - public void Setup() - { - _existigOrders = new List() - { - new Order() {Id = 2, OrderStatus = OrderStatus.Complete }, - new Order() {Id = 3, PaymentStatus = PaymentStatus.Paid }, - new Order() {Id = 1, ShippingStatus = ShippingStatus.Delivered }, - new Order() {Id = 4, OrderStatus = OrderStatus.Cancelled, PaymentStatus = PaymentStatus.Pending }, - new Order() {Id = 5, ShippingStatus = ShippingStatus.NotYetShipped, PaymentStatus = PaymentStatus.Paid }, - new Order() {Id = 6, OrderStatus = OrderStatus.Complete, ShippingStatus = ShippingStatus.ShippingNotRequired }, - new Order() {Id = 7, OrderStatus = OrderStatus.Cancelled, PaymentStatus = PaymentStatus.Refunded, ShippingStatus = ShippingStatus.NotYetShipped } - }; - - var orderRepo = MockRepository.GenerateStub>(); - orderRepo.Stub(x => x.TableNoTracking).Return(_existigOrders.AsQueryable()); - - _orderApiService = new OrderApiService(orderRepo); - } - - [Test] - [TestCase(OrderStatus.Complete)] - [TestCase(OrderStatus.Cancelled)] - public void WhenCalledWithSomeOrderStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheCountOfTheOrdersHavingThisStatus(OrderStatus orderStatus) - { - // Arange - var expectedCollectionCount = _existigOrders.Count(x => x.OrderStatus == orderStatus); - - // Act - var resultCount = _orderApiService.GetOrdersCount(status: orderStatus); - - // Assert - Assert.AreEqual(expectedCollectionCount, resultCount); - } - - [Test] - [TestCase(PaymentStatus.Paid)] - [TestCase(PaymentStatus.Refunded)] - public void WhenCalledWithSomePaymentStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheCountOfTheOrdersHavingThisStatus(PaymentStatus paymentStatus) - { - // Arange - var expectedCollectionCount = _existigOrders.Count(x => x.PaymentStatus == paymentStatus); - - // Act - var resultCount = _orderApiService.GetOrdersCount(paymentStatus: paymentStatus); - - // Assert - Assert.AreEqual(expectedCollectionCount, resultCount); - } - - [Test] - [TestCase(ShippingStatus.Delivered)] - [TestCase(ShippingStatus.ShippingNotRequired)] - public void WhenCalledWithSomeShippingStatus_GivenOrdersCollectionContainingOrdersHavingThisStatus_ShouldReturnTheCountOfTheOrdersHavingThisStatus(ShippingStatus shippingStatus) - { - // Arange - var expectedCollectionCount = _existigOrders.Count(x => x.ShippingStatus == shippingStatus); - - // Act - var resultCount = _orderApiService.GetOrdersCount(shippingStatus: shippingStatus); - - // Assert - Assert.AreEqual(expectedCollectionCount, resultCount); - } - - [Test] - public void WhenCalledWithStatus_GivenOrdersCollectionThatDoNotHaveThisStatus_ShouldReturnZero() - { - // Arange - var orderStatus = OrderStatus.Processing; - var paymentStatus = PaymentStatus.PartiallyRefunded; - var shippingStatus = ShippingStatus.Shipped; - - // Act - var resultCount = _orderApiService.GetOrdersCount(status: orderStatus) + - _orderApiService.GetOrdersCount(paymentStatus: paymentStatus) + - _orderApiService.GetOrdersCount(shippingStatus: shippingStatus); - - // Assert - Assert.AreEqual(0, resultCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingById/ProductCategoryMappingsApiServiceTests_GetById.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingById/ProductCategoryMappingsApiServiceTests_GetById.cs deleted file mode 100644 index 755df0b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingById/ProductCategoryMappingsApiServiceTests_GetById.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappingById -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetById - { - [Test] - public void WhenNullIsReturnedByTheRepository_ShouldReturnNull() - { - int mappingId = 3; - - // Arange - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.GetById(mappingId)).Return(null); - - // Act - var cut = new ProductCategoryMappingsApiService(productCategoryRepo); - var result = cut.GetById(mappingId); - - // Assert - Assert.IsNull(result); - } - - [Test] - [TestCase(-2)] - [TestCase(0)] - public void WhenNegativeOrZeroMappingIdPassed_ShouldReturnNull(int negativeOrZeroOrderId) - { - // Aranges - var mappingRepoMock = MockRepository.GenerateStub>(); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepoMock); - var result = cut.GetById(negativeOrZeroOrderId); - - // Assert - Assert.IsNull(result); - } - - [Test] - public void WhenMappingIsReturnedByTheRepository_ShouldReturnTheSameMapping() - { - int mappingId = 3; - var mapping = new ProductCategory() { Id = 3 }; - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.GetById(mappingId)).Return(mapping); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - var result = cut.GetById(mappingId); - - // Assert - Assert.AreSame(mapping, result); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_CategoryIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_CategoryIdParameter.cs deleted file mode 100644 index 2f6e601..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_CategoryIdParameter.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_CategoryIdParameter - { - [Test] - [TestCase(0)] - [TestCase(-132340)] - public void GivenNegativeOrZeroCategoryId_ShouldReturnEmptyCollection(int categoryId) - { - var repo = new List(); - - var randomNumber = new Random(); - - var currentRepoSize = randomNumber.Next(10, 100); - - for (int i = 0; i < currentRepoSize; i++) - { - repo.Add(new ProductCategory() - { - CategoryId = randomNumber.Next(10, 20), - ProductId = randomNumber.Next(1, 2), - }); - } - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(categoryId: categoryId); - - // Assert - Assert.IsEmpty(result); - } - - [Test] - public void GivenPositiveCategoryId_ShouldReturnCollectionContainingAllMappingsWithThisCategoryId() - { - var repo = new List(); - - var randomNumber = new Random(); - - var currentRepoSize = randomNumber.Next(51, 100); - - for (int i = 0; i < currentRepoSize; i++) - { - repo.Add(new ProductCategory() - { - CategoryId = randomNumber.Next(1, 2), - ProductId = randomNumber.Next(10, 20), - }); - } - - var categoryId = 1; - - repo.Add(new ProductCategory() - { - CategoryId = categoryId, - ProductId = randomNumber.Next(10, 20), - }); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(categoryId: categoryId); - - // Assert - Assert.IsTrue(result.Select(x => new { x.CategoryId, x.ProductId }) - .SequenceEqual(repo.Where(x => x.CategoryId == categoryId).Take(Configurations.DefaultLimit).Select(x => new { x.CategoryId, x.ProductId }))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_DefaultParameters.cs deleted file mode 100644 index 04e9fc3..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_DefaultParameters.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_DefaultParameters - { - [Test] - public void GivenNonEmptyValidRepositoryWithMoreThanTheMaxItems_ShouldReturnDefaultLimitItems() - { - var repo = new List(); - - var randomNumber = new Random(); - - var currentRepoSize = Configurations.MaxLimit * 2; - - for (int i = 0; i < currentRepoSize; i++) - { - repo.Add(new ProductCategory() - { - CategoryId = randomNumber.Next(10, 20), - ProductId = randomNumber.Next(1, 2), - }); - } - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(); - - // Assert - Assert.IsNotEmpty(result); - Assert.AreEqual(Configurations.DefaultLimit, result.Count); - } - - [Test] - public void GivenEmptyRepository_ShouldReturnEmptyCollection() - { - var repo = new List(); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(); - - // Assert - Assert.IsEmpty(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_LimitParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_LimitParameter.cs deleted file mode 100644 index 8a4de1b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_LimitParameter.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_LimitParameter - { - private IProductCategoryMappingsApiService _productCategoryMappingsService; - private List _existigMappings; - - // Here the product and category ids does not matter so we can use the setup method. - [SetUp] - public void Setup() - { - var randomNumber = new Random(); - - _existigMappings = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigMappings.Add(new ProductCategory() - { - ProductId = randomNumber.Next(1, 1000), - CategoryId = randomNumber.Next(1, 1000), - }); - } - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existigMappings.AsQueryable()); - - _productCategoryMappingsService = new ProductCategoryMappingsApiService(productCategoryRepo); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenMappingsAboveTheLimit_ShouldReturnCollectionWithCountEqualToTheLimit() - { - //Arange - var expectedLimit = 5; - - //Act - var categories = _productCategoryMappingsService.GetMappings(limit: expectedLimit); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedLimit, categories.Count); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenMappingsBellowTheLimit_ShouldReturnCollectionWithCountEqualToTheAvailableCategories() - { - //Arange - var expectedLimit = _existigMappings.Count(); - - //Act - var categories = _productCategoryMappingsService.GetMappings(limit: expectedLimit + 10); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(categories); - Assert.AreEqual(expectedLimit, categories.Count); - } - - [Test] - public void WhenCalledWithZeroLimitParameter_GivenSomeMappings_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = 0; - - //Act - var categories = _productCategoryMappingsService.GetMappings(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(categories); - } - - [Test] - public void WhenCalledWithNegativeLimitParameter_GivenSomeMappings_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = -10; - - //Act - var categories = _productCategoryMappingsService.GetMappings(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_PageParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_PageParameter.cs deleted file mode 100644 index 50674ab..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_PageParameter.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_PageParameter - { - private IProductCategoryMappingsApiService _mappingService; - private List _mappings; - - // Here the product and category ids does not matter so we can use the setup method. - [SetUp] - public void Setup() - { - var randomNumber = new Random(); - - _mappings = new List(); - - for (int i = 0; i < 1000; i++) - { - _mappings.Add(new ProductCategory() - { - ProductId = randomNumber.Next(1, 1000), - CategoryId = randomNumber.Next(1, 1000) - }); - } - - _mappings = _mappings.OrderBy(x => x.Id).ToList(); - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_mappings.AsQueryable()); - - _mappingService = new ProductCategoryMappingsApiService(productCategoryRepo); - } - - [Test] - public void WhenCalledWithLimitAndPageParameter_ShouldReturnTheItemsDeterminedByTheLimiAndPageParameters() - { - //Arange - var limit = 5; - var page = 6; - var expectedCollection = new ApiList(_mappings.AsQueryable(), page - 1, limit); - - //Act - var mappings = _mappingService.GetMappings(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(mappings); - Assert.AreEqual(expectedCollection.Count(), mappings.Count); - Assert.IsTrue(mappings.Select(x => new { x.CategoryId, x.ProductId }) - .SequenceEqual(expectedCollection.Select(x => new { x.CategoryId, x.ProductId }))); - } - - [Test] - public void WhenCalledWithZeroPageParameterAndSomeLimit_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = 0; - var expectedCollection = new ApiList(_mappings.AsQueryable(), page - 1, limit); - - //Act - var mappings = _mappingService.GetMappings(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(mappings); - Assert.AreEqual(expectedCollection.Count(), mappings.Count); - Assert.AreEqual(_mappings.First().Id, mappings.First().Id); - Assert.IsTrue(mappings.Select(x => new { x.CategoryId, x.ProductId }) - .SequenceEqual(expectedCollection.Select(x => new { x.CategoryId, x.ProductId }))); - } - - [Test] - public void WhenCalledWithNegativePageParameterAndSomeLimit_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = -30; - var expectedCollection = new ApiList(_mappings.AsQueryable(), page - 1, limit); - - //Act - var mappings = _mappingService.GetMappings(limit: limit, page: page); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(mappings); - Assert.AreEqual(expectedCollection.Count(), mappings.Count); - Assert.AreEqual(_mappings.First().Id, mappings.First().Id); - Assert.IsTrue(mappings.Select(x => new { x.CategoryId, x.ProductId }) - .SequenceEqual(expectedCollection.Select(x => new { x.CategoryId, x.ProductId }))); - } - - [Test] - public void WhenCalledWithLimitAndPageParameterWhichExceedTheTotalMappingsCount_ShouldReturnEmptyCollection() - { - //Arange - var limit = 5; - var page = _mappings.Count / limit + 100; - - //Act - var categories = _mappingService.GetMappings(limit: limit, page: page); - - // Assert - CollectionAssert.IsEmpty(categories); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_ProductIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_ProductIdParameter.cs deleted file mode 100644 index ac6a5e8..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_ProductIdParameter.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_ProductIdParameter - { - [Test] - [TestCase(0)] - [TestCase(-132340)] - public void GivenNegativeOrZeroProductId_ShouldReturnEmptyCollection(int productId) - { - var repo = new List(); - - var randomNumber = new Random(); - - var currentRepoSize = randomNumber.Next(10, 100); - - for (int i = 0; i < currentRepoSize; i++) - { - repo.Add(new ProductCategory() - { - CategoryId = randomNumber.Next(10, 20), - ProductId = randomNumber.Next(1, 2), - }); - } - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(productId: productId); - - // Assert - Assert.IsEmpty(result); - } - - [Test] - public void GivenPositiveProductId_ShouldReturnCollectionContainingAllMappingsWithThisProductId() - { - var repo = new List(); - - var randomNumber = new Random(); - - var productId = 1; - - repo.Add(new ProductCategory() - { - CategoryId = randomNumber.Next(10, 20), - ProductId = productId, - }); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - var result = cut.GetMappings(productId: productId); - - // Assert - Assert.IsTrue(result.Select(x => new { x.CategoryId, x.ProductId }) - .SequenceEqual(repo.Where(x => x.ProductId == productId).Select(x => new { x.CategoryId, x.ProductId }))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_SinceIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_SinceIdParameter.cs deleted file mode 100644 index c6a15c7..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappings/ProductCategoryMappingsApiServiceTests_GetMappings_SinceIdParameter.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappings -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappings_SinceIdParameter - { - private IProductCategoryMappingsApiService _productCategoryMappingsService; - private List _existigMappings; - - // Here the product and category ids does not matter so we can use the setup method. - [SetUp] - public void Setup() - { - var randomNumber = new Random(); - - _existigMappings = new List(); - - for (int i = 1; i <= 1000; i++) - { - _existigMappings.Add(new ProductCategory() - { - Id = i, - ProductId = randomNumber.Next(1, 1000), - CategoryId = randomNumber.Next(1, 1000), - }); - } - - _existigMappings = _existigMappings.OrderBy(x => x.Id).ToList(); - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existigMappings.AsQueryable()); - - _productCategoryMappingsService = new ProductCategoryMappingsApiService(productCategoryRepo); - } - - [Test] - public void WhenCalledWithValidSinceId_ShouldReturnOnlyTheMappingsAfterThisIdSortedById() - { - // Arange - var sinceId = 10; - var expectedCollection = - _existigMappings.Where(x => x.Id > sinceId).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - - // Act - var mappings = _productCategoryMappingsService.GetMappings(sinceId: 10); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(mappings); - Assert.IsTrue(expectedCollection.Select(x => x.Id).SequenceEqual(mappings.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithZeroOrNegativeSinceId_ShouldReturnAllTheMappingsSortedById(int sinceId) - { - // Arange - var expectedCollection = - _existigMappings.Where(x => x.Id > sinceId).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - - // Act - var mappings = _productCategoryMappingsService.GetMappings(sinceId: sinceId); - - // Assert - // Not Empty assert is a good practice when you assert something about collection. Because you can get a false positive if the collection is empty. - CollectionAssert.IsNotEmpty(mappings); - Assert.IsTrue(mappings.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithSinceIdOutsideOfTheCategoriesIdsRange_ShouldReturnEmptyCollection() - { - // Arange - int sinceId = int.MaxValue; - - // Act - var mappings = _productCategoryMappingsService.GetMappings(sinceId: sinceId); - - // Assert - CollectionAssert.IsEmpty(mappings); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingsCount/ProductCategoryMappingsApiServiceTests_GetMappingsCount.cs b/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingsCount/ProductCategoryMappingsApiServiceTests_GetMappingsCount.cs deleted file mode 100644 index f9a4a02..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ProductCategoryMappings/GetMappingsCount/ProductCategoryMappingsApiServiceTests_GetMappingsCount.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; -using System.Collections.Generic; -using System.Linq; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ProductCategoryMappings.GetMappingsCount -{ - [TestFixture] - public class ProductCategoryMappingsApiServiceTests_GetMappingsCount - { - private List _repo; - - [SetUp] - public void Setup() - { - _repo = new List(); - - var randomNumber = new Random(); - - var currentRepoSize = randomNumber.Next(10, 100); - - _repo.Add(new ProductCategory() - { - CategoryId = 1, - ProductId = 2, - }); - - _repo.Add(new ProductCategory() - { - CategoryId = 2, - ProductId = 1, - }); - - for (int i = 0; i < currentRepoSize; i++) - { - _repo.Add(new ProductCategory() - { - CategoryId = 1, - ProductId = randomNumber.Next(1, 2), - }); - - _repo.Add(new ProductCategory() - { - CategoryId = 2, - ProductId = randomNumber.Next(1, 2), - }); - } - } - - [Test] - public void GivenNonEmptyValidRepository_WhenCalledWithDefaultParameters_ShouldReturnRepositorySize() - { - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(_repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - int result = cut.GetMappingsCount(); - - // Assert - Assert.AreEqual(_repo.Count, result); - } - - [Test] - public void GivenEmptyRepository_WhenCalledWithDefaultParameters_ShouldReturnZero() - { - var repo = new List(); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - int result = cut.GetMappingsCount(); - - // Assert - Assert.AreEqual(0, result); - } - - [Test] - [TestCase(1, 2)] - [TestCase(1, 1)] - [TestCase(2, 1)] - [TestCase(2, 2)] - public void GivenNonEmptyValidRepository_WhenCalledWithSomeParameters_ShouldReturnCountOfAllItemsAccordingToParameters(int categoryId, int productId) - { - var expectedCount = _repo.Count(x => x.CategoryId == categoryId && x.ProductId == productId); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(_repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - int result = cut.GetMappingsCount(productId, categoryId); - - // Assert - Assert.AreEqual(expectedCount, result); - } - - [Test] - [TestCase(1)] - [TestCase(2)] - public void GivenNonEmptyValidRepository_WhenCalledWithCategoryIdParameter_ShouldReturnCountOfAllItemsThatAreMappedToThisCategory(int categoryId) - { - var expectedCount = _repo.Count(x => x.CategoryId == categoryId); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(_repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - int result = cut.GetMappingsCount(categoryId: categoryId); - - // Assert - Assert.AreEqual(expectedCount, result); - } - - [Test] - [TestCase(1)] - [TestCase(2)] - public void GivenNonEmptyValidRepository_WhenCalledWithProductIdParameter_ShouldReturnCountOfAllItemsThatAreMappedToThisProduct(int productId) - { - var expectedCount = _repo.Count(x => x.ProductId == productId); - - // Arange - var mappingRepo = MockRepository.GenerateStub>(); - mappingRepo.Stub(x => x.TableNoTracking).Return(_repo.AsQueryable()); - - // Act - var cut = new ProductCategoryMappingsApiService(mappingRepo); - - int result = cut.GetMappingsCount(productId: productId); - - // Assert - Assert.AreEqual(expectedCount, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductById/ProductApiServiceTests_GetProductById.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductById/ProductApiServiceTests_GetProductById.cs deleted file mode 100644 index 0edd168..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductById/ProductApiServiceTests_GetProductById.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductById -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductById - { - [Test] - public void WhenNullIsReturnedByTheRepository_ShouldReturnNull() - { - int productId = 3; - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.GetById(productId)).Return(null); - productRepo.Stub(x => x.Table).Return((new List()).AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var result = cut.GetProductById(productId); - - // Assert - Assert.IsNull(result); - } - - [Test] - [TestCase(-2)] - [TestCase(0)] - public void WhenNegativeOrZeroProductIdPassed_ShouldReturnNull(int negativeOrZeroProductId) - { - // Aranges - var productRepoStub = MockRepository.GenerateStub>(); - productRepoStub.Stub(x => x.Table).Return((new List()).AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepoStub, productCategoryRepo, vendorRepo, storeMappingService); - var result = cut.GetProductById(negativeOrZeroProductId); - - // Assert - Assert.IsNull(result); - } - - [Test] - public void WhenProductIsReturnedByTheRepository_ShouldReturnTheSameProduct() - { - int productId = 3; - var product = new Product() { Id = 3, Name = "some name" }; - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.GetById(productId)).Return(product); - - var list = new List(); - list.Add(product); - - productRepo.Stub(x => x.Table).Return(list.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var result = cut.GetProductById(productId); - - // Assert - Assert.AreSame(product, result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CategoryIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CategoryIdParameter.cs deleted file mode 100644 index caf3d65..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CategoryIdParameter.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_CategoryIdParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - private List _existingCategoryMappings; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2 }, - new Product() {Id = 3 }, - new Product() {Id = 1 }, - new Product() {Id = 4 }, - new Product() {Id = 5 }, - new Product() {Id = 6, Deleted = true }, - new Product() {Id = 7 } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - _existingCategoryMappings= new List() - { - new ProductCategory() { CategoryId = 1, ProductId = 2 }, - new ProductCategory() { CategoryId = 1, ProductId = 3 }, - new ProductCategory() { CategoryId = 2, ProductId = 2 }, - new ProductCategory() { CategoryId = 3, ProductId = 1 }, - new ProductCategory() { CategoryId = 4, ProductId = 4 }, - new ProductCategory() { CategoryId = 5, ProductId = 5 } - }; - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existingCategoryMappings.AsQueryable()); - - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidCategoryId_ShouldReturnOnlyTheProductsMappedToThisCategory() - { - // Arange - int categoryId = 3; - var expectedCollection = (from product in _existigProducts - join mapping in _existingCategoryMappings on product.Id equals mapping.ProductId - where mapping.CategoryId == categoryId - select product); - - // Act - var products = _productApiService.GetProducts(categoryId: categoryId); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroCategoryId_ShouldReturnEmptyCollection(int categoryId) - { - // Act - var products = _productApiService.GetProducts(categoryId: categoryId); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithCategoryIdThatDoesNotExistInTheMappings_ShouldReturnEmptyCollection(int categoryId) - { - // Act - var products = _productApiService.GetProducts(categoryId: categoryId); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CreatedParameters.cs deleted file mode 100644 index ab640c9..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_CreatedParameters.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_CreatedParameters - { - private IProductApiService _productApiService; - private List _existigProducts; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigProducts = new List() - { - new Product() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Product() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Product() {Id = 4, CreatedOnUtc = _baseDate }, - new Product() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Product() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 7, Published = false, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeProductsCreatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - - var expectedCollection = - _existigProducts.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted).OrderBy(x => x.Id); - - var expectedProductsCount = expectedCollection.Count(); - - // Act - var products = _productApiService.GetProducts(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedProductsCount, products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllProductsCreatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var products = _productApiService.GetProducts(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeProductsCreatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigProducts.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted).OrderBy(x => x.Id); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var products = _productApiService.GetProducts(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedProductsCount, products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllProductsCreatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var products = _productApiService.GetProducts(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_DefaultParameters.cs deleted file mode 100644 index 32522a3..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_DefaultParameters.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoProductsExist_ShouldReturnEmptyCollection() - { - // Arange - var productsRepo = MockRepository.GenerateStub>(); - productsRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productsRepo, productCategoryRepo, vendorRepo, storeMappingService); - var products = cut.GetProducts(); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedProductsExist_ShouldReturnEmptyCollection() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 1, Deleted = true }); - existingProducts.Add(new Product() { Id = 2, Deleted = true }); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var products = cut.GetProducts(); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedProductsExist_ShouldReturnThemSortedById() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 1 }); - existingProducts.Add(new Product() { Id = 2, Deleted = true }); - existingProducts.Add(new Product() { Id = 3 }); - - var expectedCollection = existingProducts.Where(x => !x.Deleted).OrderBy(x => x.Id); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var products = cut.GetProducts(); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeProductsExist_ShouldReturnThemSortedById() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 2, Published = false }); - existingProducts.Add(new Product() { Id = 3 }); - existingProducts.Add(new Product() { Id = 1 }); - - var expectedCollection = existingProducts.Where(x => !x.Deleted).OrderBy(x => x.Id); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var products = cut.GetProducts(); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_IdsParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_IdsParameter.cs deleted file mode 100644 index 2a59b3d..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_IdsParameter.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_IdsParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2}, - new Product() {Id = 3}, - new Product() {Id = 1}, - new Product() {Id = 4}, - new Product() {Id = 5}, - new Product() {Id = 6, Deleted = true}, - new Product() {Id = 7, Published = false} - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenProductsWithTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5 }; - - var products = _productApiService.GetProducts(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(idsCollection[0], products[0].Id); - Assert.AreEqual(idsCollection[1], products[1].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenProductsWithSomeOfTheSpecifiedIds_ShouldReturnThemSortedById() - { - var idsCollection = new List() { 1, 5, 97373, 4 }; - - var products = _productApiService.GetProducts(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(idsCollection[0], products[0].Id); - Assert.AreEqual(idsCollection[3], products[1].Id); - Assert.AreEqual(idsCollection[1], products[2].Id); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenProductsThatDoNotMatchTheSpecifiedIds_ShouldReturnEmptyCollection() - { - var idsCollection = new List() { 2123434, 5456456, 97373, -45 }; - - var products = _productApiService.GetProducts(ids: idsCollection); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithIdsParameter_GivenEmptyIdsCollection_ShouldReturnAllNotDeletedCategories() - { - var idsCollection = new List(); - - var products = _productApiService.GetProducts(ids: idsCollection); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(products.Count, _existigProducts.Count(x => !x.Deleted)); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_LimitParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_LimitParameter.cs deleted file mode 100644 index 3ad93bc..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_LimitParameter.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_LimitParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigProducts.Add(new Product() - { - Id = i + 1 - }); - } - - _existigProducts[5].Deleted = true; - _existigProducts[51].Published = false; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenProductsAboveTheLimit_ShouldReturnCollectionWithCountEqualToTheLimit() - { - //Arange - var expectedLimit = 5; - - //Act - var products = _productApiService.GetProducts(limit: expectedLimit); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedLimit, products.Count); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenProductsBellowTheLimit_ShouldReturnCollectionWithCountEqualToTheAvailableProducts() - { - //Arange - var expectedLimit = _existigProducts.Count(x => !x.Deleted); - - //Act - var products = _productApiService.GetProducts(limit: expectedLimit + 10); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedLimit, products.Count); - } - - [Test] - public void WhenCalledWithZeroLimitParameter_GivenSomeProducts_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = 0; - - //Act - var products = _productApiService.GetProducts(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithNegativeLimitParameter_GivenSomeProducts_ShouldReturnEmptyCollection() - { - //Arange - var expectedLimit = -10; - - //Act - var products = _productApiService.GetProducts(limit: expectedLimit); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PageParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PageParameter.cs deleted file mode 100644 index 8b613e8..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PageParameter.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_PageParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List(); - - for (int i = 0; i < 1000; i++) - { - _existigProducts.Add(new Product() - { - Id = i + 1 - }); - } - - _existigProducts[5].Deleted = true; - _existigProducts[51].Published = false; - _existigProducts = _existigProducts.OrderBy(x => x.Id).ToList(); - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithPageParameter_GivenLimitedProductsCollection_ShouldReturnThePartOfTheCollectionThatCorrespondsToThePage() - { - //Arange - var limit = 5; - var page = 6; - var expectedCollection = new ApiList(_existigProducts.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var products = _productApiService.GetProducts(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithZeroPageParameter_GivenLimitedProductsCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = 0; - var expectedCollection = new ApiList(_existigProducts.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var products = _productApiService.GetProducts(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.AreEqual(_existigProducts.First().Id, products.First().Id); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithNegativePageParameter_GivenLimitedProductsCollection_ShouldReturnTheFirstPage() - { - //Arange - var limit = 5; - var page = -30; - var expectedCollection = new ApiList(_existigProducts.Where(x => !x.Deleted).AsQueryable(), page - 1, limit); - - //Act - var products = _productApiService.GetProducts(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.AreEqual(_existigProducts.First().Id, products.First().Id); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithTooBigPageParameter_GivenLimitedProductsCollection_ShouldReturnEmptyCollection() - { - //Arange - var limit = 5; - var page = _existigProducts.Count / limit + 100; - - //Act - var products = _productApiService.GetProducts(limit: limit, page: page); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PublishedStatusParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PublishedStatusParameter.cs deleted file mode 100644 index bfb3fd5..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_PublishedStatusParameter.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_PublishedStatusParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2, Published = true }, - new Product() {Id = 3, Published = true }, - new Product() {Id = 1, Published = false }, - new Product() {Id = 4, Published = true }, - new Product() {Id = 5, Published = true }, - new Product() {Id = 6, Deleted = true, Published = true }, - new Product() {Id = 7, Published = false } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenAskForOnlyThePublishedProducts_ShouldReturnOnlyThePublishedProductsOrderedByid() - { - // Arange - var expectedProducts = _existigProducts.Where(x => x.Published && !x.Deleted).OrderBy(x => x.Id); - - // Act - var products = _productApiService.GetProducts(publishedStatus: true); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedProducts.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedProducts.Select(x => x.Id))); - } - - [Test] - public void WhenAskForOnlyTheUnpublishedProducts_ShouldReturnOnlyTheUnpublishedProductsCount() - { - // Arange - var expectedCollection = _existigProducts.Where(x => !x.Published && !x.Deleted).OrderBy(x => x.Id); - - // Act - var products = _productApiService.GetProducts(publishedStatus: false); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_SinceIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_SinceIdParameter.cs deleted file mode 100644 index 8230cc4..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_SinceIdParameter.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_SinceIdParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2 }, - new Product() {Id = 3 }, - new Product() {Id = 1 }, - new Product() {Id = 4 }, - new Product() {Id = 5 }, - new Product() {Id = 6, Deleted = true }, - new Product() {Id = 7 } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidSinceId_ShouldReturnOnlyTheProductsAfterThisIdSortedById() - { - // Arange - int sinceId = 3; - var expectedCollection = _existigProducts.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var products = _productApiService.GetProducts(sinceId: sinceId); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledZeroOrNegativeSinceId_ShouldReturnAllTheProductsSortedById(int sinceId) - { - // Arange - var expectedCollection = _existigProducts.Where(x => x.Id > sinceId && !x.Deleted).OrderBy(x => x.Id); - - // Act - var products = _productApiService.GetProducts(sinceId: sinceId); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledSinceIdOutsideOfTheProductsIdsRange_ShouldReturnEmptyCollection() - { - // Arange - int sinceId = int.MaxValue; - - // Act - var products = _productApiService.GetProducts(sinceId: sinceId); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_UpdatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_UpdatedParameters.cs deleted file mode 100644 index b2d621b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_UpdatedParameters.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_UpdatedParameters - { - private IProductApiService _productApiService; - private List _existigProducts; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 12); - - _existigProducts = new List() - { - new Product() {Id = 2, UpdatedOnUtc = _baseDate.AddMonths(2) }, - new Product() {Id = 3, UpdatedOnUtc = _baseDate.AddMonths(6) }, - new Product() {Id = 1, UpdatedOnUtc = _baseDate.AddMonths(7) }, - new Product() {Id = 4, UpdatedOnUtc = _baseDate }, - new Product() {Id = 5, UpdatedOnUtc = _baseDate.AddMonths(3) }, - new Product() {Id = 6, Deleted = true, UpdatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 7, Published = false, UpdatedOnUtc = _baseDate.AddMonths(4) } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenSomeProductsUpdatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = _existigProducts.Where(x => x.UpdatedOnUtc > updatedAtMinDate && !x.Deleted).OrderBy(x => x.Id); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var products = _productApiService.GetProducts(updatedAtMin: updatedAtMinDate); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedProductsCount, products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenAllProductsUpdatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(7); - - // Act - var products = _productApiService.GetProducts(updatedAtMin: updatedAtMinDate); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenSomeProductsUpdatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigProducts.Where(x => x.UpdatedOnUtc < updatedAtMaxDate && !x.Deleted).OrderBy(x => x.Id); - - var expectedProductsCount = expectedCollection.Count(); - - // Act - var products = _productApiService.GetProducts(updatedAtMax: updatedAtMaxDate); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedProductsCount, products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenAllProductsUpdatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var products = _productApiService.GetProducts(updatedAtMax: updatedAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_VendorNameParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_VendorNameParameter.cs deleted file mode 100644 index 9a388f7..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProducts/ProductApiServiceTests_GetProducts_VendorNameParameter.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProducts -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProducts_VendorNameParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - private List _existingVendors; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2, VendorId = 1}, - new Product() {Id = 3, VendorId = 2 }, - new Product() {Id = 1, VendorId = 1 }, - new Product() {Id = 4 }, - new Product() {Id = 5 }, - new Product() {Id = 6, Deleted = true, VendorId = 1 }, - new Product() {Id = 7, VendorId = 2 }, - new Product() {Id = 8, VendorId = 3 }, - new Product() {Id = 9, VendorId = 4 } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - _existingVendors = new List() - { - new Vendor() {Id = 1, Name = "vendor 1", Active = true}, - new Vendor() {Id = 2, Name = "vendor 2", Active = true}, - new Vendor() {Id = 3, Name = "vendor 3", Deleted = true}, - new Vendor() {Id = 4, Name = "vendor 4", Active = false}, - new Vendor() {Id = 5, Name = "vendor 5", Active = true} - }; - - var vendorRepo = MockRepository.GenerateStub>(); - vendorRepo.Stub(x => x.TableNoTracking).Return(_existingVendors.AsQueryable()); - - var storeMappingService = MockRepository.GenerateStub(); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - [TestCase("vendor 1")] - [TestCase("vendor 2")] - public void WhenCalledWithValidVendorName_ShouldReturnOnlyTheProductsMappedToThisVendor(string vendorName) - { - // Arange - var expectedCollection = (from product in _existigProducts - join vendor in _existingVendors on product.VendorId equals vendor.Id - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - orderby product.Id - select product); - - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenVendorCollectionWhereThisVendorIsDeleted_ShouldReturnEmptyCollections() - { - // Arange - string vendorName = "vendor 3"; - - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenVendorCollectionWhereThisVendorIsUnactive_ShouldReturnEmptyCollection() - { - // Arange - string vendorName = "vendor 4"; - - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenProductsCollectionWhereThereAreNoProductsMappedToThisVendor_ShouldReturnEmptyCollection() - { - // Arange - string vendorName = "vendor 5"; - - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsEmpty(products); - } - - [Test] - [TestCase(null)] - [TestCase("")] - public void WhenCalledWithNullOrEmptyVendorName_ShouldReturnTheEntireProductsCollectionSortedById(string vendorName) - { - // Arange - var expectedCollection = _existigProducts.Where(p => !p.Deleted).OrderBy(x => x.Id); - - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsNotEmpty(products); - Assert.AreEqual(expectedCollection.Count(), products.Count); - Assert.IsTrue(products.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase("invalid vendor name")] - [TestCase("$&@#*@(!(&%)@_@_!*%^&/sd")] - [TestCase("345")] - public void WhenCalledWithInvalidVendorName_ShouldReturnEmptyCollection(string vendorName) - { - // Act - var products = _productApiService.GetProducts(vendorName: vendorName); - - // Assert - CollectionAssert.IsEmpty(products); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CategoryIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CategoryIdParameter.cs deleted file mode 100644 index 767bbc2..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CategoryIdParameter.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductsCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_CategoryIdParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - private List _existingCategoryMappings; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2 }, - new Product() {Id = 3 }, - new Product() {Id = 1 }, - new Product() {Id = 4 }, - new Product() {Id = 5 }, - new Product() {Id = 6, Deleted = true }, - new Product() {Id = 7 } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - _existingCategoryMappings= new List() - { - new ProductCategory() { CategoryId = 1, ProductId = 2 }, - new ProductCategory() { CategoryId = 1, ProductId = 3 }, - new ProductCategory() { CategoryId = 2, ProductId = 2 }, - new ProductCategory() { CategoryId = 3, ProductId = 1 }, - new ProductCategory() { CategoryId = 4, ProductId = 4 }, - new ProductCategory() { CategoryId = 5, ProductId = 5 } - }; - - var productCategoryRepo = MockRepository.GenerateStub>(); - productCategoryRepo.Stub(x => x.TableNoTracking).Return(_existingCategoryMappings.AsQueryable()); - - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithValidCategoryId_ShouldReturnOnlyTheCountOfTheProductsMappedToThisCategory() - { - // Arange - int categoryId = 3; - var expectedCollectionCount = (from product in _existigProducts - join mapping in _existingCategoryMappings on product.Id equals mapping.ProductId - where mapping.CategoryId == categoryId - select product).Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(categoryId: categoryId); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithNegativeOrZeroCategoryId_ShouldReturnZero(int categoryId) - { - // Act - var productsCount = _productApiService.GetProductsCount(categoryId: categoryId); - - // Assert - Assert.AreEqual(0, productsCount); - } - - [Test] - [TestCase(int.MaxValue)] - [TestCase(int.MinValue)] - [TestCase(-1)] - [TestCase(5465464)] - public void WhenCalledWithCategoryIdThatDoesNotExistInTheMappings_ShouldReturnZero(int categoryId) - { - // Act - var productsCount = _productApiService.GetProductsCount(categoryId: categoryId); - - // Assert - Assert.AreEqual(0, productsCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CreatedParameters.cs deleted file mode 100644 index f865c8b..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_CreatedParameters.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductsCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_CreatedParameters - { - private IProductApiService _productApiService; - private List _existigProducts; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigProducts = new List() - { - new Product() {Id = 2, CreatedOnUtc = _baseDate.AddMonths(2) }, - new Product() {Id = 3, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 1, CreatedOnUtc = _baseDate.AddMonths(7) }, - new Product() {Id = 4, CreatedOnUtc = _baseDate }, - new Product() {Id = 5, CreatedOnUtc = _baseDate.AddMonths(3) }, - new Product() {Id = 6, Deleted = true, CreatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 7, Published = false, CreatedOnUtc = _baseDate.AddMonths(4) } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeProductsCreatedAfterThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigProducts.Where(x => x.CreatedOnUtc > createdAtMinDate && !x.Deleted); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(expectedProductsCount, productsCount); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllCategoriesCreatedBeforeThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Act - var productsCount = _productApiService.GetProductsCount(createdAtMin: createdAtMinDate); - - // Assert - Assert.AreEqual(0, productsCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeProductsCreatedBeforeThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = _existigProducts.Where(x => x.CreatedOnUtc < createdAtMaxDate && !x.Deleted); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(expectedProductsCount, productsCount); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllProductsCreatedAfterThatDate_ShouldReturnZero() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var productsCount = _productApiService.GetProductsCount(createdAtMax: createdAtMaxDate); - - // Assert - Assert.AreEqual(0, productsCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_DefaultParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_DefaultParameters.cs deleted file mode 100644 index 70e4d79..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_DefaultParameters.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductsCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_DefaultParameters - { - [Test] - public void WhenCalledWithDefaultParameters_GivenNoProductsExist_ShouldReturnZero() - { - // Arange - var productsRepo = MockRepository.GenerateStub>(); - productsRepo.Stub(x => x.TableNoTracking).Return(new List().AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new ProductApiService(productsRepo, productCategoryRepo, vendorRepo, storeMappingService); - var productsCount = cut.GetProductsCount(); - - // Assert - Assert.AreEqual(0, productsCount); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenOnlyDeletedProductsExist_ShouldReturnZero() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 1, Deleted = true }); - existingProducts.Add(new Product() { Id = 2, Deleted = true }); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var countResult = cut.GetProductsCount(); - - // Assert - Assert.AreEqual(0, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeNotDeletedProductsExist_ShouldReturnTheirCount() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 1 }); - existingProducts.Add(new Product() { Id = 2, Deleted = true }); - existingProducts.Add(new Product() { Id = 3 }); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var countResult = cut.GetProductsCount(); - - // Assert - Assert.AreEqual(2, countResult); - } - - [Test] - public void WhenCalledWithDefaultParameters_GivenSomeProductsExist_ShouldReturnTheirCount() - { - var existingProducts = new List(); - existingProducts.Add(new Product() { Id = 2, Published = false }); - existingProducts.Add(new Product() { Id = 3 }); - existingProducts.Add(new Product() { Id = 1 }); - - // Arange - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(existingProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - // Act - var cut = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - var countResult = cut.GetProductsCount(); - - // Assert - Assert.AreEqual(existingProducts.Count, countResult); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_PublishedStatusParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_PublishedStatusParameter.cs deleted file mode 100644 index 6a3d87c..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_PublishedStatusParameter.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Categories.GetCategoriesCount -{ - using Nop.Core.Domain.Stores; - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_PublishedStatusParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2, Published = true }, - new Product() {Id = 3, Published = true }, - new Product() {Id = 1, Published = false }, - new Product() {Id = 4, Published = true }, - new Product() {Id = 5, Published = true }, - new Product() {Id = 6, Deleted = true, Published = true }, - new Product() {Id = 7, Published = false } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenAskForOnlyThePublishedProducts_ShouldReturnOnlyThePublishedProductsCount() - { - // Arange - var expectedProductsCount = _existigProducts.Count(x => x.Published && !x.Deleted); - - // Act - var productsCount = _productApiService.GetProductsCount(publishedStatus: true); - - // Assert - Assert.AreEqual(expectedProductsCount, productsCount); - } - - [Test] - public void WhenAskForOnlyTheUnpublishedProducts_ShouldReturnOnlyTheUnpublishedProductsCount() - { - // Arange - var expectedCollectionCount = _existigProducts.Count(x => !x.Published && !x.Deleted); - - // Act - var productsCount = _productApiService.GetProductsCount(publishedStatus: false); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_UpdatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_UpdatedParameters.cs deleted file mode 100644 index b646085..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_UpdatedParameters.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductsCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_UpdatedParameters - { - private IProductApiService _productApiService; - private List _existigProducts; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 12); - - _existigProducts = new List() - { - new Product() {Id = 2, UpdatedOnUtc = _baseDate.AddMonths(2) }, - new Product() {Id = 3, UpdatedOnUtc = _baseDate.AddMonths(6) }, - new Product() {Id = 1, UpdatedOnUtc = _baseDate.AddMonths(7) }, - new Product() {Id = 4, UpdatedOnUtc = _baseDate }, - new Product() {Id = 5, UpdatedOnUtc = _baseDate.AddMonths(3) }, - new Product() {Id = 6, Deleted = true, UpdatedOnUtc = _baseDate.AddMonths(10) }, - new Product() {Id = 7, Published = false, UpdatedOnUtc = _baseDate.AddMonths(4) } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - var vendorRepo = MockRepository.GenerateStub>(); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenSomeProductsUpdatedAfterThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(5); - var expectedCollection = _existigProducts.Where(x => x.UpdatedOnUtc > updatedAtMinDate && !x.Deleted); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(updatedAtMin: updatedAtMinDate); - - // Assert - Assert.AreEqual(expectedProductsCount, productsCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenAllProductsUpdatedBeforeThatDate_ShouldReturnZero() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(7); - - // Act - var productsCount = _productApiService.GetProductsCount(updatedAtMin: updatedAtMinDate); - - // Assert - Assert.AreEqual(0, productsCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenSomeProductsUpdatedBeforeThatDate_ShouldReturnTheirCount() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.AddMonths(5); - var expectedCollection = - _existigProducts.Where(x => x.UpdatedOnUtc < updatedAtMaxDate && !x.Deleted); - var expectedProductsCount = expectedCollection.Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(updatedAtMax: updatedAtMaxDate); - - // Assert - Assert.AreEqual(expectedProductsCount, productsCount); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenAllProductsUpdatedAfterThatDate_ShouldReturnZero() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var productsCount = _productApiService.GetProductsCount(updatedAtMax: updatedAtMaxDate); - - // Assert - Assert.AreEqual(0, productsCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_VendorNameParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_VendorNameParameter.cs deleted file mode 100644 index 4c4dc72..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/Products/GetProductsCount/ProductApiServiceTests_GetProductsCount_VendorNameParameter.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.Products.GetProductsCount -{ - using Nop.Services.Stores; - - [TestFixture] - public class ProductApiServiceTests_GetProductsCount_VendorNameParameter - { - private IProductApiService _productApiService; - private List _existigProducts; - private List _existingVendors; - - [SetUp] - public void Setup() - { - _existigProducts = new List() - { - new Product() {Id = 2, VendorId = 1}, - new Product() {Id = 3, VendorId = 2 }, - new Product() {Id = 1, VendorId = 1 }, - new Product() {Id = 4 }, - new Product() {Id = 5 }, - new Product() {Id = 6, Deleted = true, VendorId = 1 }, - new Product() {Id = 7, VendorId = 2 }, - new Product() {Id = 8, VendorId = 3 }, - new Product() {Id = 9, VendorId = 4 } - }; - - var productRepo = MockRepository.GenerateStub>(); - productRepo.Stub(x => x.TableNoTracking).Return(_existigProducts.AsQueryable()); - - var productCategoryRepo = MockRepository.GenerateStub>(); - - _existingVendors = new List() - { - new Vendor() {Id = 1, Name = "vendor 1", Active = true}, - new Vendor() {Id = 2, Name = "vendor 2", Active = true}, - new Vendor() {Id = 3, Name = "vendor 3", Deleted = true}, - new Vendor() {Id = 4, Name = "vendor 4", Active = false}, - new Vendor() {Id = 5, Name = "vendor 5", Active = true} - }; - - var vendorRepo = MockRepository.GenerateStub>(); - vendorRepo.Stub(x => x.TableNoTracking).Return(_existingVendors.AsQueryable()); - - var storeMappingService = MockRepository.GenerateStub(); - storeMappingService.Stub(x => x.Authorize(Arg.Is.Anything)).Return(true); - - _productApiService = new ProductApiService(productRepo, productCategoryRepo, vendorRepo, storeMappingService); - } - - [Test] - [TestCase("vendor 1")] - [TestCase("vendor 2")] - public void WhenCalledWithValidVendorName_ShouldReturnOnlyTheCountOfTheProductsMappedToThisVendor(string vendorName) - { - // Arange - var expectedCollectionCount = (from product in _existigProducts - join vendor in _existingVendors on product.VendorId equals vendor.Id - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - select product).Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenVendorCollectionWhereThisVendorIsDeleted_ShouldReturnZero() - { - // Arange - string vendorName = "vendor 3"; - var expectedCollectionCount = (from product in _existigProducts - join vendor in _existingVendors on product.VendorId equals vendor.Id - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - select product).Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenVendorCollectionWhereThisVendorIsUnactive_ShouldReturnZero() - { - // Arange - string vendorName = "vendor 4"; - var expectedCollectionCount = (from product in _existigProducts - join vendor in _existingVendors on product.VendorId equals vendor.Id - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - select product).Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - public void WhenCalledWithValidVendorName_GivenProductsCollectionWhereThereAreNoProductsMappedToThisVendor_ShouldReturnZero() - { - // Arange - string vendorName = "vendor 5"; - var expectedCollectionCount = (from product in _existigProducts - join vendor in _existingVendors on product.VendorId equals vendor.Id - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - select product).Count(); - - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - [TestCase(null)] - [TestCase("")] - public void WhenCalledWithNullOrEmptyVendorName_ShouldReturnTheEntireCollectionCount(string vendorName) - { - // Arange - var expectedCollectionCount = _existigProducts.Count(p => !p.Deleted); - - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(expectedCollectionCount, productsCount); - } - - [Test] - [TestCase("invalid vendor name")] - [TestCase("$&@#*@(!(&%)@_@_!*%^&/sd")] - [TestCase("345")] - public void WhenCalledWithInvalidVendorName_ShouldReturnZero(string vendorName) - { - // Act - var productsCount = _productApiService.GetProductsCount(vendorName: vendorName); - - // Assert - Assert.AreEqual(0, productsCount); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CreatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CreatedParameters.cs deleted file mode 100644 index af07236..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CreatedParameters.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ShoppingCartItems.GetShoppingCartItems -{ - using Nop.Core; - using Nop.Core.Domain.Stores; - - [TestFixture] - public class ShoppingCartItemsTests_GetShoppingCartItems_CreatedParameters - { - private IShoppingCartItemApiService _shoppingCartItemsApiService; - private List _existigShoppingCartItems; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigShoppingCartItems = new List(); - var randomNumber = new Random(); - - for (int i = 1; i <= 1000; i++) - { - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = i, - CreatedOnUtc = _baseDate.AddMonths(randomNumber.Next(1, 10)) - }); - } - - var shoppingCartItemsRepo = MockRepository.GenerateStub>(); - shoppingCartItemsRepo.Stub(x => x.TableNoTracking).Return(_existigShoppingCartItems.AsQueryable()); - - var storeContext = MockRepository.GenerateStub(); - storeContext.Stub(x => x.CurrentStore).Return(new Store() - { - Id = 0 - }); - - _shoppingCartItemsApiService = new ShoppingCartItemApiService(shoppingCartItemsRepo, storeContext); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenSomeShoppingCartItemsCreatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(5); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - CreatedOnUtc = createdAtMinDate - }); - - var expectedCollection = - _existigShoppingCartItems.Where(x => x.CreatedOnUtc > createdAtMinDate).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - - var expectedProductsCount = expectedCollection.Count(); - - // Act - var shoppingCartItems = _shoppingCartItemsApiService.GetShoppingCartItems(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsNotEmpty(shoppingCartItems); - Assert.AreEqual(expectedProductsCount, shoppingCartItems.Count); - Assert.IsTrue(shoppingCartItems.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMinParameter_GivenAllShoppingCartItemsCreatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMinDate = _baseDate.AddMonths(11); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - CreatedOnUtc = createdAtMinDate - }); - - // Act - var shoppingCartItems = _shoppingCartItemsApiService.GetShoppingCartItems(createdAtMin: createdAtMinDate); - - // Assert - CollectionAssert.IsEmpty(shoppingCartItems); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenSomeShoppingCartItemsCreatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime createdAtMaxDate = _baseDate.AddMonths(5); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - CreatedOnUtc = createdAtMaxDate - }); - - var expectedCollection = _existigShoppingCartItems.Where(x => x.CreatedOnUtc < createdAtMaxDate).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - var expectedShoppingCartItemsCount = expectedCollection.Count(); - - // Act - var shoppingCartItems = _shoppingCartItemsApiService.GetShoppingCartItems(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsNotEmpty(shoppingCartItems); - Assert.AreEqual(expectedShoppingCartItemsCount, shoppingCartItems.Count); - Assert.IsTrue(shoppingCartItems.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithCreatedAtMaxParameter_GivenAllShoppingCartItemsCreatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime createdAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var shoppingCartItems = _shoppingCartItemsApiService.GetShoppingCartItems(createdAtMax: createdAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(shoppingCartItems); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CustomerIdParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CustomerIdParameter.cs deleted file mode 100644 index 6cb7823..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_CustomerIdParameter.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ShoppingCartItems.GetShoppingCartItems -{ - using Nop.Core; - using Nop.Core.Domain.Stores; - - [TestFixture] - public class ShoppingCartItemsTests_GetShoppingCartItems_CustomerIdParameter - { - private IShoppingCartItemApiService _shoppingCartItemApiService; - private List _shoppingCartItems; - - [SetUp] - public void Setup() - { - var randomNumber = new Random(); - - _shoppingCartItems = new List(); - - for (int i = 1; i <= 1000; i++) - { - _shoppingCartItems.Add(new ShoppingCartItem() - { - Id = i, - CustomerId = randomNumber.Next(1, 10) - }); - } - - var shoppingCartItemsRepo = MockRepository.GenerateStub>(); - shoppingCartItemsRepo.Stub(x => x.TableNoTracking).Return(_shoppingCartItems.AsQueryable()); - - var storeContext = MockRepository.GenerateStub(); - storeContext.Stub(x => x.CurrentStore).Return(new Store() - { - Id = 0 - }); - - _shoppingCartItemApiService = new ShoppingCartItemApiService(shoppingCartItemsRepo, storeContext); - } - - [Test] - public void WhenPassedPositiveCustomerId_GivenShoppingCartItemsForThisCustomer_ShouldReturnOnlyTheShoppingCartItemsForThisCustomerSortedById() - { - // Arange - int customerId = 5; - var expectedResult = _shoppingCartItems.Where(x => x.CustomerId == customerId).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - - // Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(customerId); - - // Assert - Assert.IsTrue(expectedResult.Select(x => new {x.Id, x.CustomerId}) - .SequenceEqual(result.Select(x => new {x.Id, x.CustomerId}))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenPassedNegativeOrZeroCustomerId_ShouldReturnEmptyCollection(int customerId) - { - // Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(customerId); - - // Assert - Assert.IsEmpty(result); - } - - [Test] - public void WhenPassedNonExistentCustomerId_ShouldReturnEmptyCollection() - { - // Arange - int nonExistendCustomerId = int.MaxValue; - - // Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(nonExistendCustomerId); - - // Assert - Assert.IsEmpty(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_LimitParameter.cs b/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_LimitParameter.cs deleted file mode 100644 index 40c90e1..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_LimitParameter.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ShoppingCartItems.GetShoppingCartItems -{ - using Nop.Core; - using Nop.Core.Domain.Stores; - - [TestFixture] - public class ShoppingCartItemsTests_GetShoppingCartItems_LimitParameter - { - private IShoppingCartItemApiService _shoppingCartItemApiService; - private List _existigShoppingCartItems; - - [SetUp] - public void Setup() - { - _existigShoppingCartItems = new List(); - - for (int i = 1; i <= 1000; i++) - { - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = i - }); - } - - var shoppingCartItemRepo = MockRepository.GenerateStub>(); - shoppingCartItemRepo.Stub(x => x.TableNoTracking).Return(_existigShoppingCartItems.AsQueryable()); - - var storeContext = MockRepository.GenerateStub(); - storeContext.Stub(x => x.CurrentStore).Return(new Store() - { - Id = 0 - }); - - _shoppingCartItemApiService = new ShoppingCartItemApiService(shoppingCartItemRepo, storeContext); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenMoreShoppingCartItemsThanTheLimit_ShouldReturnCollectionWithCountEqualToTheLimit() - { - //Arange - var expectedLimit = 5; - - //Act - var shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(limit: expectedLimit); - - // Assert - CollectionAssert.IsNotEmpty(shoppingCartItems); - Assert.AreEqual(expectedLimit, shoppingCartItems.Count); - } - - [Test] - public void WhenCalledWithLimitParameter_GivenShoppingCartItemsBellowTheLimit_ShouldReturnCollectionWithCountEqualToPassedLimit() - { - //Arange - var limit = Configurations.MaxLimit + 10; - - //Act - var shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(limit: limit); - - // Assert - CollectionAssert.IsNotEmpty(shoppingCartItems); - Assert.AreEqual(limit, shoppingCartItems.Count); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithZeroOrNegativeLimitParameter_GivenSomeProducts_ShouldReturnEmptyCollection(int limit) - { - //Act - var shoppingCartItems = _shoppingCartItemApiService.GetShoppingCartItems(limit: limit); - - // Assert - CollectionAssert.IsEmpty(shoppingCartItems); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_PageParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_PageParameters.cs deleted file mode 100644 index aa7f006..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_PageParameters.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ShoppingCartItems.GetShoppingCartItems -{ - using Nop.Core; - using Nop.Core.Domain.Stores; - - [TestFixture] - public class ShoppingCartItemsTests_GetShoppingCartItems_PageParameters - { - private IShoppingCartItemApiService _shoppingCartItemApiService; - private List _existigShoppingCartItems; - - [SetUp] - public void Setup() - { - _existigShoppingCartItems = new List(); - - for (int i = 1; i <= 1000; i++) - { - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = i - }); - } - - var shoppingCartItemRepo = MockRepository.GenerateStub>(); - shoppingCartItemRepo.Stub(x => x.TableNoTracking).Return(_existigShoppingCartItems.AsQueryable()); - - var storeContext = MockRepository.GenerateStub(); - storeContext.Stub(x => x.CurrentStore).Return(new Store() - { - Id = 0 - }); - - _shoppingCartItemApiService = new ShoppingCartItemApiService(shoppingCartItemRepo, storeContext); - } - - [Test] - public void WhenCalledWithPageParameter_ShouldReturnThePartOfTheCollectionThatCorrespondsToThePage() - { - //Arange - var limit = 5; - var page = 6; - var expectedCollection = new ApiList(_existigShoppingCartItems.AsQueryable(), page - 1, limit); - - //Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual(expectedCollection.Count(), result.Count); - Assert.IsTrue(result.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - [TestCase(0)] - [TestCase(-10)] - public void WhenCalledWithZeroOrNegativePageParameter_ShouldReturnTheFirstPage(int page) - { - //Arange - var limit = 5; - var expectedCollection = new ApiList(_existigShoppingCartItems.AsQueryable(), page - 1, limit); - - //Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(limit: limit, page: page); - - // Assert - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual(expectedCollection.Count(), result.Count); - Assert.AreEqual(_existigShoppingCartItems.First().Id, result.First().Id); - Assert.IsTrue(result.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithTooBigPageParameter_ShouldReturnEmptyCollection() - { - //Arange - var limit = 5; - var page = _existigShoppingCartItems.Count / limit + 100; - - //Act - var result = _shoppingCartItemApiService.GetShoppingCartItems(limit: limit, page: page); - - // Assert - CollectionAssert.IsEmpty(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_UpdatedParameters.cs b/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_UpdatedParameters.cs deleted file mode 100644 index a58ef7f..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/ShoppingCartItems/GetShoppingCartItems/ShoppingCartItemsTests_GetShoppingCartItems_UpdatedParameters.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests.ShoppingCartItems.GetShoppingCartItems -{ - using Nop.Core; - using Nop.Core.Domain.Stores; - - [TestFixture] - public class ShoppingCartItemsTests_GetShoppingCartItems_UpdatedParameters - { - private IShoppingCartItemApiService _shoppingCartItemsApiService; - private List _existigShoppingCartItems; - private DateTime _baseDate; - - [SetUp] - public void Setup() - { - _baseDate = new DateTime(2016, 2, 23); - - _existigShoppingCartItems = new List(); - var randomNumber = new Random(); - - for (int i = 1; i <= 1000; i++) - { - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = i, - UpdatedOnUtc = _baseDate.AddMonths(randomNumber.Next(1, 10)) - }); - } - - var shoppingCartItemsRepo = MockRepository.GenerateStub>(); - shoppingCartItemsRepo.Stub(x => x.TableNoTracking).Return(_existigShoppingCartItems.AsQueryable()); - - var storeContext = MockRepository.GenerateStub(); - storeContext.Stub(x => x.CurrentStore).Return(new Store() - { - Id = 0 - }); - - _shoppingCartItemsApiService = new ShoppingCartItemApiService(shoppingCartItemsRepo, storeContext); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenSomeShoppingCartItemsUpdatedAfterThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(5); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - UpdatedOnUtc = updatedAtMinDate - }); - - var expectedCollection = _existigShoppingCartItems.Where(x => x.UpdatedOnUtc > updatedAtMinDate).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - var expectedShoppingCartItemsCount = expectedCollection.Count(); - - // Act - var result = _shoppingCartItemsApiService.GetShoppingCartItems(updatedAtMin: updatedAtMinDate); - - // Assert - Assert.AreEqual(expectedShoppingCartItemsCount, result.Count); - Assert.IsTrue(result.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMinParameter_GivenAllShoppingCartItemsUpdatedBeforeThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMinDate = _baseDate.AddMonths(11); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - UpdatedOnUtc = updatedAtMinDate - }); - - // Act - var result = _shoppingCartItemsApiService.GetShoppingCartItems(updatedAtMin: updatedAtMinDate); - - // Assert - CollectionAssert.IsEmpty(result); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenSomeShoppingCartItemsUpdatedBeforeThatDate_ShouldReturnThemSortedById() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.AddMonths(5); - - // Ensure that the date will be in the collection because in the setup method we are using a random number to generate the dates. - _existigShoppingCartItems.Add(new ShoppingCartItem() - { - Id = _existigShoppingCartItems.Count + 1, - UpdatedOnUtc = updatedAtMaxDate - }); - - var expectedCollection = - _existigShoppingCartItems.Where(x => x.UpdatedOnUtc < updatedAtMaxDate).OrderBy(x => x.Id).Take(Configurations.DefaultLimit); - - var expectedShoppingCartItemsCount = expectedCollection.Count(); - - // Act - var shoppingCartItems = _shoppingCartItemsApiService.GetShoppingCartItems(updatedAtMax: updatedAtMaxDate); - - // Assert - Assert.AreEqual(expectedShoppingCartItemsCount, shoppingCartItems.Count); - Assert.IsTrue(shoppingCartItems.Select(x => x.Id).SequenceEqual(expectedCollection.Select(x => x.Id))); - } - - [Test] - public void WhenCalledWithUpdatedAtMaxParameter_GivenAllProductsUpdatedAfterThatDate_ShouldReturnEmptyCollection() - { - // Arange - DateTime updatedAtMaxDate = _baseDate.Subtract(new TimeSpan(365)); // subtract one year - - // Act - var result = _shoppingCartItemsApiService.GetShoppingCartItems(updatedAtMax: updatedAtMaxDate); - - // Assert - CollectionAssert.IsEmpty(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ServicesTests/StateProvinceApiServiceTests.cs b/Nop.Plugin.Api.Tests/ServicesTests/StateProvinceApiServiceTests.cs deleted file mode 100644 index a467c7a..0000000 --- a/Nop.Plugin.Api.Tests/ServicesTests/StateProvinceApiServiceTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Directory; -using Nop.Plugin.Api.Services; -using NUnit.Framework; -using Rhino.Mocks; - -namespace Nop.Plugin.Api.Tests.ServicesTests -{ - //[TestFixture] - //public class StateProvinceApiServiceTests - //{ - // private IStateProvinceApiService _stateProvinceApiService; - - // [SetUp] - // public new void SetUp() - // { - // var stateProvinceRepositoryStub = MockRepository.GenerateStub>(); - - // stateProvinceRepositoryStub.Stub(x => x.Table).Return((new List() - // { - // new StateProvince() - // { - // Name = "test state 1" - // }, - // new StateProvince() - // { - // Name = "test state 2" - // } - // }).AsQueryable()); - - // _stateProvinceApiService = new StateProvinceApiService(stateProvinceRepositoryStub); - // } - - // [Test] - // public void Get_state_by_existing_name() - // { - // StateProvince state = _stateProvinceApiService.GetStateProvinceByName("test state 1"); - - // Assert.IsNotNull(state); - // Assert.AreEqual("test state 1", state.Name); - // } - - // [Test] - // public void Get_state_by_non_existing_name() - // { - // StateProvince state = _stateProvinceApiService.GetStateProvinceByName("non existing state name"); - - // Assert.IsNull(state); - // } - //} -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/SetUp.cs b/Nop.Plugin.Api.Tests/SetUp.cs deleted file mode 100644 index 9c19b58..0000000 --- a/Nop.Plugin.Api.Tests/SetUp.cs +++ /dev/null @@ -1,16 +0,0 @@ -using NUnit.Framework; - -namespace Nop.Plugin.Api.Tests -{ - [SetUpFixture] - public class SetUp - { - [OneTimeSetUp] - public void RunBeforeAnyTests() - { - // We need to create all the mappings before any of the test are run - // All maps are created in the ApiMapperConfiguration constructor. - ApiMapperConfiguration mapps = new ApiMapperConfiguration(); - } - } -} diff --git a/Nop.Plugin.Api.Tests/ValidatorTests/FieldsValidatorTests_GetValidFields.cs b/Nop.Plugin.Api.Tests/ValidatorTests/FieldsValidatorTests_GetValidFields.cs deleted file mode 100644 index 13344d5..0000000 --- a/Nop.Plugin.Api.Tests/ValidatorTests/FieldsValidatorTests_GetValidFields.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; -using Nop.Plugin.Api.Tests.SerializersTests.DummyObjects; -using Nop.Plugin.Api.Validators; - -namespace Nop.Plugin.Api.Tests.ValidatorTests -{ - public class FieldsValidatorTests_GetValidFields - { - [Test] - [TestCase("")] - [TestCase(null)] - public void WhenEmptyFieldsParameterPassed_ShouldReturnEmptyDictionary(string emptyFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(emptyFields, typeof(DummyObjectWithSimpleTypes)); - - // Assert - Assert.IsEmpty(result); - } - - [Test] - [TestCase("first_property")] - [TestCase("second_property")] - [TestCase("first_property,second_property")] - [TestCase("firstproperty,secondproperty")] - [TestCase("firstProperty,secondproperty")] - public void WhenOnlyValidFieldsParameterPassed_ShouldReturnNonEmptyDictionary(string validFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(validFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.IsNotEmpty(result); - } - - [Test] - [TestCase("first_property,second_property")] - [TestCase("firstproperty,secondproperty")] - [TestCase("firstProperty,Secondproperty")] - public void WhenValidFieldsParameterPassed_ShouldReturnDictionaryContainingEachValidField(string validFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(validFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.True(result.ContainsKey("firstproperty")); - Assert.True(result.ContainsKey("secondproperty")); - } - - [Test] - [TestCase("FiRst_PropertY,second_property")] - [TestCase("firstproperty,SecondProPerty")] - [TestCase("firstProperty,Secondproperty")] - public void WhenValidFieldsParameterPassed_ShouldReturnDictionaryContainingEachValidFieldWithLowercase(string validFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(validFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.True(result.ContainsKey("firstproperty")); - Assert.True(result.ContainsKey("secondproperty")); - } - - [Test] - [TestCase("first_property")] - public void WhenValidFieldParameterPassed_ShouldReturnDictionaryContainingTheFieldWithoutUnderscores(string validField) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(validField, typeof(DummyObjectWithSimpleTypes)); - - Assert.True(result.ContainsKey("firstproperty")); - } - - [Test] - [TestCase("first_property,second_property,invalid")] - [TestCase("firstproperty,secondproperty,invalid")] - [TestCase("firstProperty,Secondproperty,invalid")] - public void WhenValidAndInvalidFieldsParameterPassed_ShouldReturnDictionaryWithValidFieldsOnly(string mixedFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(mixedFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.AreEqual(2, result.Count); - Assert.True(result.ContainsKey("firstproperty")); - Assert.True(result.ContainsKey("secondproperty")); - } - - [Test] - [TestCase("invalid")] - [TestCase("multiple,invalid,fields")] - public void WhenInvalidFieldsParameterPassed_ShouldReturnEmptyDictionary(string invalidFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(invalidFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.IsEmpty(result); - } - - [Test] - [TestCase("invalid,,")] - [TestCase(",,,*multiple,)in&^valid,f@#%$ields+_-,,,,,")] - [TestCase(".")] - [TestCase(",")] - [TestCase("()")] - [TestCase("'\"\"")] - [TestCase(",,,,mail, 545, ''\"")] - [TestCase("peshoid")] - public void WhenInvalidFieldsWithSpecialSymbolsParameterPassed_ShouldReturnEmptyDictionary(string invalidFields) - { - //Arange - var cut = new FieldsValidator(); - - //Act - Dictionary result = cut.GetValidFields(invalidFields, typeof(DummyObjectWithSimpleTypes)); - - Assert.IsEmpty(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/ValidatorTests/TypeValidatorTests_IsValid.cs b/Nop.Plugin.Api.Tests/ValidatorTests/TypeValidatorTests_IsValid.cs deleted file mode 100644 index bf5b556..0000000 --- a/Nop.Plugin.Api.Tests/ValidatorTests/TypeValidatorTests_IsValid.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Threading; -using Nop.Plugin.Api.DTOs.Products; -using NUnit.Framework; -using Nop.Plugin.Api.Tests.SerializersTests.DummyObjects; -using Nop.Plugin.Api.Validators; - -namespace Nop.Plugin.Api.Tests.ValidatorTests -{ - public class TypeValidatorTests_IsValid - { - [Test] - [SetCulture("de-de")] - [Description("Regression test for issue #11 - https://github.com/SevenSpikes/api-plugin-for-nopcommerce/issues/11")] - public void WhenCurrentCultureUsesCommaAsDecimalPoint_ShouldProperlyValidateProductPrice() - { - //Arange - Dictionary properties = new Dictionary(); - properties.Add("price", 33.33); - - var cut = new TypeValidator(); - - //Act - bool result = cut.IsValid(properties); - - // Assert - Assert.IsTrue(result); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api.Tests/app.config b/Nop.Plugin.Api.Tests/app.config deleted file mode 100644 index 1f561e5..0000000 --- a/Nop.Plugin.Api.Tests/app.config +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Nop.Plugin.Api.Tests/packages.config b/Nop.Plugin.Api.Tests/packages.config deleted file mode 100644 index 1e68407..0000000 --- a/Nop.Plugin.Api.Tests/packages.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/Nop.Plugin.Api.csproj b/Nop.Plugin.Api.csproj new file mode 100644 index 0000000..9be634d --- /dev/null +++ b/Nop.Plugin.Api.csproj @@ -0,0 +1,88 @@ + + + + netcoreapp3.1 + This plugin allows you to access/create Nop resources outside of the system + true + false + + true + + + + ..\..\Nop-4.3\Presentation\Nop.Web\Plugins\Nop.Plugin.Api\ + $(OutputPath) + true + false + + + + + ..\..\Nop-4.3\Presentation\Nop.Web\Plugins\Nop.Plugin.Api\ + $(OutputPath) + true + false + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Nop.Plugin.Api.csproj.user b/Nop.Plugin.Api.csproj.user new file mode 100644 index 0000000..0b0f24d --- /dev/null +++ b/Nop.Plugin.Api.csproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/Nop.Plugin.Api/ApiAuthentication.cs b/Nop.Plugin.Api/ApiAuthentication.cs deleted file mode 100644 index 7194c90..0000000 --- a/Nop.Plugin.Api/ApiAuthentication.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Nop.Plugin.Api -{ - using System.Collections.Generic; - using System.Linq; - using System.Security.Cryptography.X509Certificates; - using IdentityModel; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.IdentityModel.Tokens; - using Nop.Plugin.Api.Helpers; - using Nop.Services.Authentication.External; - using Org.BouncyCastle.Asn1.X509.Qualified; - - public class ApiAuthentication : IExternalAuthenticationRegistrar - { - public void Configure(AuthenticationBuilder builder) - { - RsaSecurityKey signingKey = CryptoHelper.CreateRsaSecurityKey(); - - builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwt => - { - jwt.Audience = "nop_api"; - jwt.TokenValidationParameters = new TokenValidationParameters - { - ValidateActor = false, - ValidateIssuer = false, - NameClaimType = JwtClaimTypes.Name, - RoleClaimType = JwtClaimTypes.Role, - // Uncomment this if you are using an certificate to sign your tokens. - // IssuerSigningKey = new X509SecurityKey(cert), - IssuerSigningKeyResolver = (string token, SecurityToken securityToken, string kid, - TokenValidationParameters validationParameters) => - new List { signingKey } - }; - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/ApiMapperConfiguration.cs b/Nop.Plugin.Api/ApiMapperConfiguration.cs deleted file mode 100644 index e933ae5..0000000 --- a/Nop.Plugin.Api/ApiMapperConfiguration.cs +++ /dev/null @@ -1,202 +0,0 @@ -using AutoMapper; -using IdentityServer4.EntityFramework.Entities; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Common; -using Nop.Core.Domain.Customers; -using Nop.Core.Domain.Directory; -using Nop.Core.Domain.Localization; -using Nop.Core.Domain.Messages; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Stores; -using Nop.Core.Infrastructure.Mapper; -using Nop.Plugin.Api.AutoMapper; -using Nop.Plugin.Api.Domain; -using Nop.Plugin.Api.DTOs; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.DTOs.CustomerRoles; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.DTOs.Languages; -using Nop.Plugin.Api.DTOs.Manufacturers; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.DTOs.ProductAttributes; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.DTOs.ProductManufacturerMappings; -using Nop.Plugin.Api.DTOs.Products; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; -using Nop.Plugin.Api.DTOs.Stores; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Plugin.Api.Models; -using System.Collections.Generic; -using System.Linq; -using System.Net; - -namespace Nop.Plugin.Api -{ - public class ApiMapperConfiguration : Profile, IOrderedMapperProfile - { - public ApiMapperConfiguration() - { - CreateMap(); - CreateMap(); - - CreateMap(); - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateClientToClientApiModelMap(); - - CreateAddressMap(); - CreateAddressDtoToEntityMap(); - CreateShoppingCartItemMap(); - - CreateCustomerToDTOMap(); - CreateCustomerToOrderCustomerDTOMap(); - CreateCustomerDTOToOrderCustomerDTOMap(); - CreateCustomerForShoppingCartItemMapFromCustomer(); - - CreateMap(); - CreateOrderEntityToOrderDtoMap(); - - CreateProductMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - - CreateMap(); - CreateMap(); - - CreateMap(); - CreateMap(); - } - - public int Order => 0; - - private new static void CreateMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting(); - } - - private static void CreateClientToClientApiModelMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .ForMember(x => x.ClientSecret, y => y.MapFrom(src => src.ClientSecrets.FirstOrDefault().Description)) - .ForMember(x => x.RedirectUrl, y => y.MapFrom(src => src.RedirectUris.FirstOrDefault().RedirectUri)) - .ForMember(x => x.AccessTokenLifetime, y => y.MapFrom(src => src.AccessTokenLifetime)) - .ForMember(x => x.RefreshTokenLifetime, y => y.MapFrom(src => src.AbsoluteRefreshTokenLifetime)); - } - - private void CreateOrderEntityToOrderDtoMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)) - .ForMember(x => x.OrderItems, y => y.MapFrom(src => src.OrderItems.Select(x => x.ToDto()))); - } - - private void CreateAddressMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)) - .ForMember(x => x.CountryName, - y => y.MapFrom(src => src.Country.GetWithDefault(x => x, new Country()).Name)) - .ForMember(x => x.StateProvinceName, - y => y.MapFrom(src => src.StateProvince.GetWithDefault(x => x, new StateProvince()).Name)); - } - - private void CreateAddressDtoToEntityMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)); - } - - private void CreateCustomerForShoppingCartItemMapFromCustomer() - { - AutoMapperApiConfiguration.MapperConfigurationExpression - .CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)) - .ForMember(x => x.BillingAddress, - y => y.MapFrom(src => src.BillingAddress.GetWithDefault(x => x, new Address()).ToDto())) - .ForMember(x => x.ShippingAddress, - y => y.MapFrom(src => src.ShippingAddress.GetWithDefault(x => x, new Address()).ToDto())) - .ForMember(x => x.Addresses, - y => y.MapFrom(src => - src.Addresses.GetWithDefault(x => x, new List
()).Select(address => address.ToDto()))); - } - - private void CreateCustomerToDTOMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.Id, y => y.MapFrom(src => src.Id)) - .ForMember(x => x.BillingAddress, - y => y.MapFrom(src => src.BillingAddress.GetWithDefault(x => x, new Address()).ToDto())) - .ForMember(x => x.ShippingAddress, - y => y.MapFrom(src => src.ShippingAddress.GetWithDefault(x => x, new Address()).ToDto())) - .ForMember(x => x.Addresses, - y => - y.MapFrom( - src => - src.Addresses.GetWithDefault(x => x, new List
()) - .Select(address => address.ToDto()))) - .ForMember(x => x.ShoppingCartItems, - y => - y.MapFrom( - src => - src.ShoppingCartItems.GetWithDefault(x => x, new List()) - .Select(item => item.ToDto()))) - .ForMember(x => x.RoleIds, y => y.MapFrom(src => src.CustomerRoles.Select(z => z.Id))); - } - - private void CreateCustomerToOrderCustomerDTOMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting(); - } - - private void CreateCustomerDTOToOrderCustomerDTOMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting(); - } - - private void CreateShoppingCartItemMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.CustomerDto, - y => y.MapFrom(src => - src.Customer.GetWithDefault(x => x, new Customer()).ToCustomerForShoppingCartItemDto())) - .ForMember(x => x.ProductDto, - y => y.MapFrom(src => src.Product.GetWithDefault(x => x, new Product()).ToDto())); - } - - private void CreateProductMap() - { - AutoMapperApiConfiguration.MapperConfigurationExpression.CreateMap() - .IgnoreAllNonExisting() - .ForMember(x => x.FullDescription, y => y.MapFrom(src => WebUtility.HtmlEncode(src.FullDescription))) - .ForMember(x => x.Tags, - y => y.MapFrom(src => src.ProductProductTagMappings.Select(x => x.ProductTag.Name))); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/ApiPlugin.cs b/Nop.Plugin.Api/ApiPlugin.cs deleted file mode 100644 index ae5591d..0000000 --- a/Nop.Plugin.Api/ApiPlugin.cs +++ /dev/null @@ -1,244 +0,0 @@ -namespace Nop.Plugin.Api -{ - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Migrations; - using Nop.Core; - using Nop.Core.Infrastructure; - using Nop.Core.Plugins; - using Nop.Plugin.Api.Data; - using Nop.Plugin.Api.Domain; - using Nop.Plugin.Api.Helpers; - using Nop.Services.Configuration; - using Nop.Services.Localization; - using Nop.Web.Framework.Menu; - - public class ApiPlugin : BasePlugin, IAdminMenuPlugin - { - //private readonly IWebConfigMangerHelper _webConfigMangerHelper; - private readonly ApiObjectContext _objectContext; - private readonly ISettingService _settingService; - private readonly IWorkContext _workContext; - private readonly IWebHelper _webHelper; - private readonly ILocalizationService _localizationService; - - public ApiPlugin(ApiObjectContext objectContext,/*IWebConfigMangerHelper webConfigMangerHelper,*/ ISettingService settingService, IWorkContext workContext, - ILocalizationService localizationService, IWebHelper webHelper -/*, IConfiguration configuration*/) - { - _objectContext = objectContext; - //_webConfigMangerHelper = webConfigMangerHelper; - _settingService = settingService; - _workContext = workContext; - _localizationService = localizationService; - _webHelper = webHelper; - //_configuration = configuration; - } - - //private readonly IConfiguration _configuration; - - public override void Install() - { - var configManagerHelper = new NopConfigManagerHelper(); - - // some of third party libaries that we use for WebHooks and Swagger use older versions - // of certain assemblies so we need to redirect them to the those that nopCommerce uses - // TODO: Upgrade 4.1. check this! - //configManagerHelper.AddBindingRedirects(); - - // required by the WebHooks support - // TODO: Upgrade 4.1. check this! - //configManagerHelper.AddConnectionString(); - - _objectContext.Install(); - - //locales - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api", "Api plugin"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.ManageClients", "Manage Api Clients"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Configure", "Configure Web Api"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.GeneralSettings", "General Settings"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableApi", "Enable Api"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableApi.Hint", "By checking this settings you can Enable/Disable the Web Api"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.AllowRequestsFromSwagger", "Allow Requests From Swagger"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.AllowRequestsFromSwagger.Hint", "Swagger is the documentation generation tool used for the API (/Swagger). It has a client that enables it to make GET requests to the API endpoints. By enabling this option you will allow all requests from the swagger client. Do Not Enable on live site, it is only for demo sites or local testing!!!"); - - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Title","API"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Settings.Title","Settings"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Clients.Title", "Clients"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Menu.Docs.Title", "Docs"); - - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Page.Settings.Title", "Api Settings"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Page.Clients.Title", "Api Clients"); - - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Page.Clients.Create.Title", "Add a new Api client"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Page.Clients.Edit.Title", "Edit Api client"); - - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.Name", "Name"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.Name.Hint", "Name Hint"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.ClientId", "Client Id"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.ClientId.Hint", "The id of the client"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.ClientSecret", "Client Secret"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.ClientSecret.Hint", "The client secret is used during the authentication for obtaining the Access Token"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.CallbackUrl", "Callback Url"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.CallbackUrl.Hint", "The url where the Authorization code will be send"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.IsActive", "Is Active"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.IsActive.Hint", "You can use it to enable/disable the access to your store for the client"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.AddNew", "Add New Client"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.Edit", "Edit"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.Created", "Created"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.Deleted", "Deleted"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.Name", "Name is required"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientId", "Client Id is required"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientSecret", "Client Secret is required"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.CallbackUrl", "Callback Url is required"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Settings.GeneralSettingsTitle", "General Settings"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Edit", "Edit"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.Client.BackToList", "Back To List"); - - _localizationService.AddOrUpdatePluginLocaleResource("Api.Categories.Fields.Id.Invalid", "Id is invalid"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidPropertyType", "Invalid Property Type"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidType", "Invalid {0} type"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidRequest", "Invalid request"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidRootProperty", "Invalid root property"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.NoJsonProvided", "No Json provided"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.InvalidJsonFormat", "Json format is invalid"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageAttachmentFormat", "Invalid image attachment base64 format"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageSrc", "Invalid image source"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.Category.InvalidImageSrcType", "You have provided an invalid image source/attachment "); - - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.CouldNotRegisterWebhook", "Could not register WebHook due to error: {0}"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.CouldNotRegisterDuplicateWebhook", "Could not register WebHook because a webhook with the same URI and Filters is already registered."); - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.CouldNotUpdateWebhook", "Could not update WebHook due to error: {0}"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.CouldNotDeleteWebhook", "Could not delete WebHook due to error: {0}"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.CouldNotDeleteWebhooks", "Could not delete WebHooks due to error: {0}"); - _localizationService.AddOrUpdatePluginLocaleResource("Api.WebHooks.InvalidFilters", "The following filters are not valid: '{0}'. A list of valid filters can be obtained from the path '{1}'."); - - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableLogging", "Enable Logging"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Api.Admin.EnableLogging.Hint", "By enable logging you will see webhook messages in the Log. These messages are needed ONLY for diagnostic purposes. NOTE: A restart is required when changing this setting in order to take effect"); - - ApiSettings settings = new ApiSettings - { - EnableApi = true, - AllowRequestsFromSwagger = false - }; - - _settingService.SaveSetting(settings); - - base.Install(); - - // Changes to Web.Config trigger application restart. - // This doesn't appear to affect the Install function, but just to be safe we will made web.config changes after the plugin was installed. - //_webConfigMangerHelper.AddConfiguration(); - } - - public override void Uninstall() - { - _objectContext.Uninstall(); - - var persistedGrantMigrator = EngineContext.Current.Resolve().GetService(); - persistedGrantMigrator.Migrate("0"); - - var configurationMigrator = EngineContext.Current.Resolve().GetService(); - configurationMigrator.Migrate("0"); - - // TODO: Delete all resources - //locales - _localizationService.DeletePluginLocaleResource("Plugins.Api"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Menu.ManageClients"); - - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Menu.Title"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Menu.Settings.Title"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Menu.Clients.Title"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Menu.Docs.Title"); - - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Configure"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.GeneralSettings"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.EnableApi"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.EnableApi.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.AllowRequestsFromSwagger"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.AllowRequestsFromSwagger.Hint"); - - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.Name"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.ClientId"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.ClientSecret"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.CallbackUrl"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.IsActive"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.AddNew"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.Edit"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.Created"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.Deleted"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.Name"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientId"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientSecret"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.CallbackUrl"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Settings.GeneralSettingsTitle"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Edit"); - _localizationService.DeletePluginLocaleResource("Plugins.Api.Admin.Client.BackToList"); - - _localizationService.DeletePluginLocaleResource("Api.WebHooks.CouldNotRegisterWebhook"); - _localizationService.DeletePluginLocaleResource("Api.WebHooks.CouldNotRegisterDuplicateWebhook"); - _localizationService.DeletePluginLocaleResource("Api.WebHooks.CouldNotUpdateWebhook"); - _localizationService.DeletePluginLocaleResource("Api.WebHooks.CouldNotDeleteWebhook"); - _localizationService.DeletePluginLocaleResource("Api.WebHooks.CouldNotDeleteWebhooks"); - _localizationService.DeletePluginLocaleResource("Api.WebHooks.InvalidFilters"); - - base.Uninstall(); - - // Changes to Web.Config trigger application restart. - // This doesn't appear to affect the uninstall function, but just to be safe we will made web.config changes after the plugin was uninstalled. - //_webConfigMangerHelper.RemoveConfiguration(); - } - - public void ManageSiteMap(SiteMapNode rootNode) - { - string pluginMenuName = _localizationService.GetResource("Plugins.Api.Admin.Menu.Title",languageId: _workContext.WorkingLanguage.Id, defaultValue: "API"); - - string settingsMenuName = _localizationService.GetResource("Plugins.Api.Admin.Menu.Settings.Title", languageId: _workContext.WorkingLanguage.Id, defaultValue: "API"); - - string manageClientsMenuName = _localizationService.GetResource("Plugins.Api.Admin.Menu.Clients.Title", languageId: _workContext.WorkingLanguage.Id, defaultValue: "API"); - - const string adminUrlPart = "Admin/"; - - var pluginMainMenu = new SiteMapNode - { - Title = pluginMenuName, - Visible = true, - SystemName = "Api-Main-Menu", - IconClass = "fa-genderless" - }; - - pluginMainMenu.ChildNodes.Add(new SiteMapNode - { - Title = settingsMenuName, - Url = _webHelper.GetStoreLocation() + adminUrlPart + "ApiAdmin/Settings", - Visible = true, - SystemName = "Api-Settings-Menu", - IconClass = "fa-genderless" - }); - - pluginMainMenu.ChildNodes.Add(new SiteMapNode - { - Title = manageClientsMenuName, - Url = _webHelper.GetStoreLocation() + adminUrlPart + "ManageClientsAdmin/List", - Visible = true, - SystemName = "Api-Clients-Menu", - IconClass = "fa-genderless" - }); - - - string pluginDocumentationUrl = "https://github.com/SevenSpikes/api-plugin-for-nopcommerce"; - - pluginMainMenu.ChildNodes.Add(new SiteMapNode - { - Title = _localizationService.GetResource("Plugins.Api.Admin.Menu.Docs.Title"), - Url = pluginDocumentationUrl, - Visible = true, - SystemName = "Api-Docs-Menu", - IconClass = "fa-genderless" - });//TODO: target="_blank" - - - rootNode.ChildNodes.Add(pluginMainMenu); - } - } -} diff --git a/Nop.Plugin.Api/ApiStartup.cs b/Nop.Plugin.Api/ApiStartup.cs deleted file mode 100644 index 9916e55..0000000 --- a/Nop.Plugin.Api/ApiStartup.cs +++ /dev/null @@ -1,314 +0,0 @@ -using Nop.Plugin.Api.Data; -using Nop.Web.Framework.Infrastructure.Extensions; - -namespace Nop.Plugin.Api -{ - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Entities; - using IdentityServer4.Hosting; - using IdentityServer4.Models; - using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Rewrite; - using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.IdentityModel.Tokens; - using Nop.Core.Data; - using Nop.Core.Infrastructure; - using Nop.Plugin.Api.Authorization.Policies; - using Nop.Plugin.Api.Authorization.Requirements; - using Nop.Plugin.Api.Constants; - using Nop.Plugin.Api.Helpers; - using Nop.Plugin.Api.IdentityServer.Endpoints; - using Nop.Plugin.Api.IdentityServer.Generators; - using Nop.Plugin.Api.IdentityServer.Middlewares; - using Nop.Web.Framework.Infrastructure; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IdentityModel.Tokens.Jwt; - using System.IO; - using System.Linq; - using System.Linq.Dynamic.Core; - using System.Reflection; - using ApiResource = IdentityServer4.EntityFramework.Entities.ApiResource; - - public class ApiStartup : INopStartup - { - private const string ObjectContextName = "nop_object_context_web_api"; - - // TODO: extract all methods into extensions. - public void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddDbContext(optionsBuilder => - { - optionsBuilder.UseSqlServerWithLazyLoading(services); - }); - - AddRequiredConfiguration(); - - AddBindingRedirectsFallbacks(); - - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - - AddTokenGenerationPipeline(services); - - AddAuthorizationPipeline(services); - } - - public void Configure(IApplicationBuilder app) - { - // During a clean install we should not register any middlewares i.e IdentityServer as it won't be able to create its - // tables without a connection string and will throw an exception - var dataSettings = DataSettingsManager.LoadSettings(); - if (!dataSettings?.IsValid ?? true) - return; - - // The default route templates for the Swagger docs and swagger - ui are "swagger/docs/{apiVersion}" and "swagger/ui/index#/{assetPath}" respectively. - //app.UseSwagger(); - //app.UseSwaggerUI(options => - // { - // //var currentAssembly = Assembly.GetAssembly(this.GetType()); - // //var currentAssemblyName = currentAssembly.GetName().Name; - - // //Needeed for removing the "Try It Out" button from the post and put methods. - // //http://stackoverflow.com/questions/36772032/swagger-5-2-3-supportedsubmitmethods-removed/36780806#36780806 - - // //options.InjectOnCompleteJavaScript($"{currentAssemblyName}.Scripts.swaggerPostPutTryItOutButtonsRemoval.js"); - - // options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); - // } - //); - - // This needs to be called here because in the plugin install method identity server is not yet registered. - ApplyIdentityServerMigrations(app); - - SeedData(app); - - - var rewriteOptions = new RewriteOptions() - .AddRewrite("oauth/(.*)", "connect/$1", true) - .AddRewrite("api/token", "connect/token", true); - - app.UseRewriter(rewriteOptions); - - app.UseMiddleware(); - - ////uncomment only if the client is an angular application that directly calls the oauth endpoint - //// app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); - UseIdentityServer(app); - - //need to enable rewind so we can read the request body multiple times (this should eventually be refactored, but both JsonModelBinder and all of the DTO validators need to read this stream) - app.Use(async (context, next) => - { - context.Request.EnableBuffering(); - await next(); - }); - } - - private void UseIdentityServer(IApplicationBuilder app) - { - // The code below is a copy of app.UseIdentityServer(); - // but the nopCommerce AuthenticationMiddleware is added by nopCommmerce and - // it has a try catch for the non-configured properly external authentication providers i.e Facebook - // So there is no need to call UseAuthentication again and thus not being able to catch exceptions thrown by Facebook - - //app.Validate(); - UseMiddlewareExtensions.UseMiddleware(app); - app.ConfigureCors(); - //app.UseAuthentication(); - UseMiddlewareExtensions.UseMiddleware(app); - } - - private void AddRequiredConfiguration() - { - var configManagerHelper = new NopConfigManagerHelper(); - - // some of third party libaries that we use for WebHooks and Swagger use older versions - // of certain assemblies so we need to redirect them to the once that nopCommerce uses - //TODO: Upgrade 4.10 check this! - //configManagerHelper.AddBindingRedirects(); - - // required by the WebHooks support - //TODO: Upgrade 4.10 check this! - //configManagerHelper.AddConnectionString(); - - // This is required only in development. - // It it is required only when you want to send a web hook to an https address with an invalid SSL certificate. (self-signed) - // The code marks all certificates as valid. - // We may want to extract this as a setting in the future. - - // NOTE: If this code is commented the certificates will be validated. - System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; - } - - private void AddAuthorizationPipeline(IServiceCollection services) - { - services.AddAuthorization(options => - { - options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, - policy => - { - policy.Requirements.Add(new ActiveApiPluginRequirement()); - policy.Requirements.Add(new AuthorizationSchemeRequirement()); - policy.Requirements.Add(new ActiveClientRequirement()); - policy.Requirements.Add(new RequestFromSwaggerOptional()); - policy.RequireAuthenticatedUser(); - }); - }); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - } - - private void AddTokenGenerationPipeline(IServiceCollection services) - { - RsaSecurityKey signingKey = CryptoHelper.CreateRsaSecurityKey(); - - DataSettings dataSettings = DataSettingsManager.LoadSettings(); - if (!dataSettings?.IsValid ?? true) - return; - - string connectionStringFromNop = dataSettings.DataConnectionString; - - var migrationsAssembly = typeof(ApiStartup).GetTypeInfo().Assembly.GetName().Name; - - services.AddIdentityServer() - .AddSigningCredential(signingKey) - .AddConfigurationStore(options => - { - options.ConfigureDbContext = builder => - builder.UseSqlServer(connectionStringFromNop, - sql => sql.MigrationsAssembly(migrationsAssembly)); - }) - .AddOperationalStore(options => - { - options.ConfigureDbContext = builder => - builder.UseSqlServer(connectionStringFromNop, - sql => sql.MigrationsAssembly(migrationsAssembly)); - }) - .AddAuthorizeInteractionResponseGenerator() - .AddEndpoint("Authorize", "/oauth/authorize/callback") - .AddEndpoint("Authorize", "/oauth/authorize") - .AddEndpoint("Token", "/oauth/token"); - } - - private void ApplyIdentityServerMigrations(IApplicationBuilder app) - { - using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) - { - // the database.Migrate command will apply all pending migrations and will create the database if it is not created already. - var persistedGrantContext = serviceScope.ServiceProvider.GetRequiredService(); - persistedGrantContext.Database.Migrate(); - - var configurationContext = serviceScope.ServiceProvider.GetRequiredService(); - configurationContext.Database.Migrate(); - } - } - - private void SeedData(IApplicationBuilder app) - { - using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) - { - var configurationContext = serviceScope.ServiceProvider.GetRequiredService(); - - if (!configurationContext.ApiResources.Any()) - { - // In the simple case an API has exactly one scope. But there are cases where you might want to sub-divide the functionality of an API, and give different clients access to different parts. - configurationContext.ApiResources.Add(new ApiResource() - { - Enabled = true, - Scopes = new List() - { - new ApiScope() - { - Name = "nop_api", - DisplayName = "nop_api" - } - }, - Name = "nop_api" - }); - - configurationContext.SaveChanges(); - - TryRunUpgradeScript(configurationContext); - } - } - } - - private string LoadUpgradeScript() - { - var fileProvider = EngineContext.Current.Resolve(); - string path = fileProvider.MapPath("~/Plugins/Nop.Plugin.Api/upgrade_script.sql"); - string script = File.ReadAllText(path); - - return script; - } - - private void TryRunUpgradeScript(ConfigurationDbContext configurationContext) - { - try - { - // If there are no api resources we can assume that this is the first start after the upgrade and run the upgrade script. - string upgradeScript = LoadUpgradeScript(); - configurationContext.Database.ExecuteSqlCommand(upgradeScript); - - // All client secrets must be hashed otherwise the identity server validation will fail. - var allClients = - Enumerable.ToList(configurationContext.Clients.Include(client => client.ClientSecrets)); - foreach (var client in allClients) - { - foreach (var clientSecret in client.ClientSecrets) - { - clientSecret.Value = HashExtensions.Sha256(clientSecret.Value); - } - - client.AccessTokenLifetime = Configurations.DefaultAccessTokenExpiration; - client.AbsoluteRefreshTokenLifetime = Configurations.DefaultRefreshTokenExpiration; - } - - configurationContext.SaveChanges(); - } - catch (Exception ex) - { - // Probably the upgrade script was already executed and we don't need to do anything. - } - } - - public void AddBindingRedirectsFallbacks() - { - // If no binding redirects are present in the config file then this will perform the binding redirect - RedirectAssembly("Microsoft.AspNetCore.DataProtection.Abstractions", new Version(2, 0, 0, 0), "adb9793829ddae60"); - } - - ///Adds an AssemblyResolve handler to redirect all attempts to load a specific assembly name to the specified version. - public static void RedirectAssembly(string shortName, Version targetVersion, string publicKeyToken) - { - ResolveEventHandler handler = null; - - handler = (sender, args) => - { - // Use latest strong name & version when trying to load SDK assemblies - var requestedAssembly = new AssemblyName(args.Name); - if (requestedAssembly.Name != shortName) - return null; - - requestedAssembly.Version = targetVersion; - requestedAssembly.SetPublicKeyToken(new AssemblyName("x, PublicKeyToken=" + publicKeyToken).GetPublicKeyToken()); - requestedAssembly.CultureInfo = CultureInfo.InvariantCulture; - - AppDomain.CurrentDomain.AssemblyResolve -= handler; - - return Assembly.Load(requestedAssembly); - }; - AppDomain.CurrentDomain.AssemblyResolve += handler; - } - - public int Order => new AuthenticationStartup().Order + 1; - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Attributes/ApiAuthorize.cs b/Nop.Plugin.Api/Attributes/ApiAuthorize.cs deleted file mode 100644 index 86677b3..0000000 --- a/Nop.Plugin.Api/Attributes/ApiAuthorize.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Nop.Plugin.Api.Attributes -{ - using Microsoft.AspNetCore.Authorization; - using Core.Plugins; - - // We need the ApiAuthorize attribute because when the api plugin assembly is loaded in memory by PluginManager - // all of its attributes are being initialized by the .NetFramework. - // The authorize attribute of the api plugin is marked with the Bearer authentication scheme, but the scheme is registered in the ApiStartup class, - // which is called on plugin install. - // If the plugin is not installed the authorize attribute will still be initialized when the assembly is loaded in memory, but the scheme won't be registered, - // which will cause an exception. - // That is why we need to make sure that the plugin is installed before setting the scheme. - public class ApiAuthorize : AuthorizeAttribute - { - public new string Policy - { - get => base.AuthenticationSchemes; - set => base.AuthenticationSchemes = GetAuthenticationSchemeName(value); - } - - public new string AuthenticationSchemes - { - get => base.AuthenticationSchemes; - set => base.AuthenticationSchemes = GetAuthenticationSchemeName(value); - } - - private static string GetAuthenticationSchemeName(string value) - { - var pluginInstalled = PluginManager.FindPlugin(typeof(ApiStartup))?.Installed ?? false; - - if (pluginInstalled) - { - return value; - } - - return default(string); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Policies/ActiveClientAuthorizationPolicy.cs b/Nop.Plugin.Api/Authorization/Policies/ActiveClientAuthorizationPolicy.cs deleted file mode 100644 index 882ac78..0000000 --- a/Nop.Plugin.Api/Authorization/Policies/ActiveClientAuthorizationPolicy.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Nop.Plugin.Api.Authorization.Policies -{ - using System.Threading.Tasks; - using Microsoft.AspNetCore.Authorization; - using Nop.Plugin.Api.Authorization.Requirements; - - public class ActiveClientAuthorizationPolicy : AuthorizationHandler - { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ActiveClientRequirement requirement) - { - if (requirement.IsClientActive()) - { - context.Succeed(requirement); - } - else - { - context.Fail(); - } - - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Policies/RequestsFromSwaggerAuthorizationPolicy.cs b/Nop.Plugin.Api/Authorization/Policies/RequestsFromSwaggerAuthorizationPolicy.cs deleted file mode 100644 index 143872e..0000000 --- a/Nop.Plugin.Api/Authorization/Policies/RequestsFromSwaggerAuthorizationPolicy.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Nop.Plugin.Api.Authorization.Policies -{ - using System.Threading.Tasks; - using Microsoft.AspNetCore.Authorization; - using Nop.Plugin.Api.Authorization.Requirements; - - public class RequestsFromSwaggerAuthorizationPolicy : AuthorizationHandler - { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequestFromSwaggerOptional requirement) - { - if (requirement.AllowRequestsFromSwagger()) - { - if (requirement.IsRequestFromSwagger(context.Resource as string)) - { - context.Succeed(requirement); - } - else - { - context.Fail(); - } - } - else - { - context.Succeed(requirement); - } - - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs b/Nop.Plugin.Api/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs deleted file mode 100644 index 9eacd77..0000000 --- a/Nop.Plugin.Api/Authorization/Policies/ValidSchemeAuthorizationPolicy.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Nop.Plugin.Api.Authorization.Policies -{ - using System.Threading.Tasks; - using Microsoft.AspNetCore.Authorization; - using Nop.Plugin.Api.Authorization.Requirements; - - public class ValidSchemeAuthorizationPolicy : AuthorizationHandler - { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizationSchemeRequirement requirement) - { - var mvcContext = context.Resource as - Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext; - - if (requirement.IsValid(mvcContext?.HttpContext.Request.Headers)) - { - context.Succeed(requirement); - } - else - { - context.Fail(); - } - - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Requirements/ActiveClientRequirement.cs b/Nop.Plugin.Api/Authorization/Requirements/ActiveClientRequirement.cs deleted file mode 100644 index bb2117f..0000000 --- a/Nop.Plugin.Api/Authorization/Requirements/ActiveClientRequirement.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Nop.Plugin.Api.Authorization.Requirements -{ - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Http; - using Nop.Core.Infrastructure; - using Nop.Plugin.Api.Services; - - public class ActiveClientRequirement : IAuthorizationRequirement - { - public bool IsClientActive() - { - if (!ClientExistsAndActive()) - { - // don't authorize if any of the above is not true - return false; - } - - return true; - } - - private bool ClientExistsAndActive() - { - var httpContextAccessor = EngineContext.Current.Resolve(); - - var clientId = - httpContextAccessor.HttpContext.User.FindFirst("client_id")?.Value; - - if (clientId != null) - { - var clientService = EngineContext.Current.Resolve(); - var client = clientService.FindClientByClientId(clientId); - - if (client != null && client.Enabled) - { - return true; - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Authorization/Requirements/RequestFromSwaggerOptional.cs b/Nop.Plugin.Api/Authorization/Requirements/RequestFromSwaggerOptional.cs deleted file mode 100644 index f1b7357..0000000 --- a/Nop.Plugin.Api/Authorization/Requirements/RequestFromSwaggerOptional.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Nop.Plugin.Api.Authorization.Requirements -{ - using Microsoft.AspNetCore.Authorization; - using Nop.Core.Infrastructure; - using Nop.Plugin.Api.Domain; - - public class RequestFromSwaggerOptional : IAuthorizationRequirement - { - public bool IsRequestFromSwagger(string requestReferrer) - { - // Swagger client does not support BearerToken authentication. - // That is why we don't check for Bearer token authentication but check only 2 things: - // 1. The store owner explicitly has allowed Swagger to make requests to the API - // 2. Check if the request really comes from Swagger documentation page. Since Swagger documentation page is located on /swagger/index we simply check that the Refferer contains "swagger" - if (requestReferrer != null && requestReferrer.Contains("swagger")) - { - return true; - } - - return true; - } - - public bool AllowRequestsFromSwagger() - { - var settings = EngineContext.Current.Resolve(); - - return settings.AllowRequestsFromSwagger; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Constants/Configurations.cs b/Nop.Plugin.Api/Constants/Configurations.cs deleted file mode 100644 index 2c3300d..0000000 --- a/Nop.Plugin.Api/Constants/Configurations.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Nop.Plugin.Api.Constants -{ - public class Configurations - { - // time is in seconds (10 years = 315360000 seconds) and should not exceed 2038 year - // https://stackoverflow.com/questions/43593074/jwt-validation-fails/43605820 - public const int DefaultAccessTokenExpiration = 315360000; - public const int DefaultRefreshTokenExpiration = int.MaxValue; - public const int DefaultLimit = 50; - public const int DefaultPageValue = 1; - public const int DefaultSinceId = 0; - public const int DefaultCustomerId = 0; - public const string DefaultOrder = "Id"; - public const int MaxLimit = 250; - public const int MinLimit = 1; - public const string PublishedStatus = "published"; - public const string UnpublishedStatus = "unpublished"; - public const string AnyStatus = "any"; - public const string JsonTypeMapsPattern = "json.maps"; - - public const string NEWSLETTER_SUBSCRIBERS_KEY = "Nop.api.newslettersubscribers"; - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Constants/ViewNames.cs b/Nop.Plugin.Api/Constants/ViewNames.cs deleted file mode 100644 index 326d2b1..0000000 --- a/Nop.Plugin.Api/Constants/ViewNames.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Nop.Plugin.Api.Constants -{ - public class ViewNames - { - public const string AdminApiSettings = "~/Plugins/Nop.Plugin.Api/Views/Settings.cshtml"; - public const string AdminApiClientsCreateOrUpdate = "~/Plugins/Nop.Plugin.Api/Views/Clients/CreateOrUpdate.cshtml"; - public const string AdminApiClientsSettings = "~/Plugins/Nop.Plugin.Api/Views/Clients/ClientSettings.cshtml"; - public const string AdminApiClientsList = "~/Plugins/Nop.Plugin.Api/Views/Clients/List.cshtml"; - public const string AdminApiClientsCreate = "~/Plugins/Nop.Plugin.Api/Views/Clients/Create.cshtml"; - public const string AdminApiClientsEdit = "~/Plugins/Nop.Plugin.Api/Views/Clients/Edit.cshtml"; - public const string AdminLayout = "_AdminLayout"; - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Constants/WebHookNames.cs b/Nop.Plugin.Api/Constants/WebHookNames.cs deleted file mode 100644 index 9738e94..0000000 --- a/Nop.Plugin.Api/Constants/WebHookNames.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Nop.Plugin.Api.Constants -{ - public static class WebHookNames - { - public const string FiltersGetAction = "FiltersGetAction"; - - public const string GetWebhookByIdAction = "GetWebHookByIdAction"; - - public const string CustomersCreate = "customers/create"; - public const string CustomersUpdate = "customers/update"; - public const string CustomersDelete = "customers/delete"; - - public const string ProductsCreate = "products/create"; - public const string ProductsUpdate = "products/update"; - public const string ProductsDelete = "products/delete"; - public const string ProductsUnmap = "products/unmap"; - - public const string CategoriesCreate = "categories/create"; - public const string CategoriesUpdate = "categories/update"; - public const string CategoriesDelete = "categories/delete"; - public const string CategoriesUnmap = "categories/unmap"; - - public const string OrdersCreate = "orders/create"; - public const string OrdersUpdate = "orders/update"; - public const string OrdersDelete = "orders/delete"; - - public const string ProductCategoryMapsCreate = "product_category_maps/create"; - public const string ProductCategoryMapsUpdate = "product_category_maps/update"; - public const string ProductCategoryMapsDelete = "product_category_maps/delete"; - - public const string StoresUpdate = "stores/update"; - - public const string LanguagesCreate = "languages/create"; - public const string LanguagesUpdate = "languages/update"; - public const string LanguagesDelete = "languages/delete"; - - public const string NewsLetterSubscriptionCreate = "news_letter_subscription/create"; - public const string NewsLetterSubscriptionUpdate = "news_letter_subscription/update"; - public const string NewsLetterSubscriptionDelete = "news_letter_subscription/delete"; - } -} diff --git a/Nop.Plugin.Api/Controllers/Admin/ManageClientsAdminController.cs b/Nop.Plugin.Api/Controllers/Admin/ManageClientsAdminController.cs deleted file mode 100644 index ec63dfa..0000000 --- a/Nop.Plugin.Api/Controllers/Admin/ManageClientsAdminController.cs +++ /dev/null @@ -1,116 +0,0 @@ -namespace Nop.Plugin.Api.Controllers.Admin -{ - using System.Linq; - using Microsoft.AspNetCore.Mvc; - using Constants; - using Nop.Services.Localization; - using Web.Framework; - using Nop.Web.Framework.Controllers; - using Web.Framework.Kendoui; - using Web.Framework.Mvc.Filters; - using Models; - using Services; - using System; - - [AuthorizeAdmin] - [Area(AreaNames.Admin)] - [Route("admin/manageClientsAdmin/")] - public class ManageClientsAdminController : BasePluginController - { - private readonly IClientService _clientService; - private readonly ILocalizationService _localizationService; - - public ManageClientsAdminController(ILocalizationService localizationService, IClientService clientService) - { - _localizationService = localizationService; - _clientService = clientService; - } - - [HttpGet] - [Route("list")] - public ActionResult List() - { - return View(ViewNames.AdminApiClientsList); - } - - [HttpPost] - [Route("list")] - public ActionResult List(DataSourceRequest command) - { - var gridModel = _clientService.GetAllClients(); - - var grids = new DataSourceResult() - { - Data = gridModel, - Total = gridModel.Count() - }; - - return Json(grids); - } - - [HttpGet] - [Route("create")] - public ActionResult Create() - { - var clientModel = new ClientApiModel - { - Enabled = true, - ClientSecret = Guid.NewGuid().ToString(), - ClientId = Guid.NewGuid().ToString(), - AccessTokenLifetime = Configurations.DefaultAccessTokenExpiration, - RefreshTokenLifetime = Configurations.DefaultRefreshTokenExpiration - }; - - return View(ViewNames.AdminApiClientsCreate, clientModel); - } - - [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")] - [Route("create")] - public ActionResult Create(ClientApiModel model, bool continueEditing) - { - if (ModelState.IsValid) - { - var clientId = _clientService.InsertClient(model); - - SuccessNotification(_localizationService.GetResource("Plugins.Api.Admin.Client.Created")); - return continueEditing ? RedirectToAction("Edit", new { id = clientId }) : RedirectToAction("List"); - } - - return RedirectToAction("List"); - } - - [HttpGet] - [Route("edit/{id}")] - public IActionResult Edit(int id) - { - var clientModel = _clientService.FindClientByIdAsync(id); - - return View(ViewNames.AdminApiClientsEdit, clientModel); - } - - [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")] - [Route("edit/{id}")] - public IActionResult Edit(ClientApiModel model, bool continueEditing) - { - if (ModelState.IsValid) - { - _clientService.UpdateClient(model); - - SuccessNotification(_localizationService.GetResource("Plugins.Api.Admin.Client.Edit")); - return continueEditing ? RedirectToAction("Edit", new { id = model.Id }) : RedirectToAction("List"); - } - - return RedirectToAction("List"); - } - - [HttpPost, ActionName("Delete")] - [Route("delete/{id}")] - public IActionResult DeleteConfirmed(int id) - { - _clientService.DeleteClient(id); - - SuccessNotification(_localizationService.GetResource("Plugins.Api.Admin.Client.Deleted")); - return RedirectToAction("List"); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Controllers/WebHookFiltersController.cs b/Nop.Plugin.Api/Controllers/WebHookFiltersController.cs deleted file mode 100644 index 14a1feb..0000000 --- a/Nop.Plugin.Api/Controllers/WebHookFiltersController.cs +++ /dev/null @@ -1,60 +0,0 @@ -//using System.Collections.Generic; -//using System.Threading.Tasks; -//using Microsoft.AspNetCore.Mvc; -//using Nop.Plugin.Api.Attributes; -//using Nop.Plugin.Api.JSON.Serializers; -//using Nop.Services.Customers; -//using Nop.Services.Discounts; -//using Nop.Services.Localization; -//using Nop.Services.Logging; -//using Nop.Services.Media; -//using Nop.Services.Security; -//using Nop.Services.Stores; - -//namespace Nop.Plugin.Api.Controllers -//{ -// using System.Net; -// using Microsoft.AspNet.WebHooks; -// using Microsoft.AspNetCore.Authentication.JwtBearer; -// using Microsoft.AspNetCore.Authorization; -// using Nop.Plugin.Api.Services; - -// [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] -// public class WebHookFiltersController : BaseApiController -// { -// private readonly IWebHookFilterManager _filterManager; - -// public WebHookFiltersController(IJsonFieldsSerializer jsonFieldsSerializer, -// IAclService aclService, -// ICustomerService customerService, -// IStoreMappingService storeMappingService, -// IStoreService storeService, -// IDiscountService discountService, -// ICustomerActivityService customerActivityService, -// ILocalizationService localizationService, -// IPictureService pictureService, -// IWebHookService webHookService) : -// base(jsonFieldsSerializer, -// aclService, -// customerService, -// storeMappingService, -// storeService, -// discountService, -// customerActivityService, -// localizationService, -// pictureService) -// { -// _filterManager = webHookService.GetWebHookFilterManager(); -// } - -// [HttpGet] -// [Route("/api/webhooks/filters")] -// [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] -// [GetRequestsErrorInterceptorActionFilter] -// public async Task> GetWebHookFilters() -// { -// IDictionary filters = await _filterManager.GetAllWebHookFiltersAsync(); -// return filters.Values; -// } -// } -//} diff --git a/Nop.Plugin.Api/Controllers/WebHookRegistrationsController.cs b/Nop.Plugin.Api/Controllers/WebHookRegistrationsController.cs deleted file mode 100644 index d801c11..0000000 --- a/Nop.Plugin.Api/Controllers/WebHookRegistrationsController.cs +++ /dev/null @@ -1,434 +0,0 @@ -//using Nop.Plugin.Api.Attributes; -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; -//using Nop.Plugin.Api.JSON.Serializers; -//using Nop.Services.Customers; -//using Nop.Services.Discounts; -//using Nop.Services.Localization; -//using Nop.Services.Logging; -//using Nop.Services.Security; -//using Nop.Services.Stores; -//using Nop.Core.Domain.Stores; -//using System.Net.Http; -//using System.Net; -//using System.Globalization; -//using Nop.Core; -//using Nop.Plugin.Api.Constants; -//using Nop.Services.Media; -//using Microsoft.AspNetCore.Mvc; -//using Microsoft.AspNet.WebHooks; -//using Nop.Plugin.Api.Services; - -//namespace Nop.Plugin.Api.Controllers -//{ -// using System.Security; -// using System.Security.Claims; -// using IdentityServer4.EntityFramework.Entities; -// using IdentityServer4.Stores; -// using Microsoft.AspNetCore.Authentication.JwtBearer; -// using Microsoft.AspNetCore.Authorization; -// using Microsoft.AspNetCore.Http; -// using Nop.Plugin.Api.JSON.Serializers; - -// [ApiAuthorize(Policy = JwtBearerDefaults.AuthenticationScheme, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] -// public class WebHookRegistrationsController : BaseApiController -// { -// private const string ErrorPropertyKey = "webhook"; -// private const string PRIVATE_FILTER_PREFIX = "MS_Private_"; - -// private readonly IWebHookManager _manager; -// private readonly IWebHookStore _store; -// private readonly IWebHookFilterManager _filterManager; -// private readonly IStoreContext _storeContext; -// private readonly IHttpContextAccessor _httpContextAccessor; -// private readonly IClientStore _clientStore; - -// public WebHookRegistrationsController(IJsonFieldsSerializer jsonFieldsSerializer, -// IAclService aclService, -// ICustomerService customerService, -// IStoreMappingService storeMappingService, -// IStoreService storeService, -// IDiscountService discountService, -// ICustomerActivityService customerActivityService, -// ILocalizationService localizationService, -// IPictureService pictureService, -// IStoreContext storeContext, -// IWebHookService webHookService, -// IHttpContextAccessor httpContextAccessor, -// IClientStore clientStore) -// : base(jsonFieldsSerializer, -// aclService, customerService, -// storeMappingService, -// storeService, -// discountService, -// customerActivityService, -// localizationService, -// pictureService) -// { -// _storeContext = storeContext; -// _manager = webHookService.GetWebHookManager(); -// _store = webHookService.GetWebHookStore(); -// _filterManager = webHookService.GetWebHookFilterManager(); -// _httpContextAccessor = httpContextAccessor; -// _clientStore = clientStore; -// } - -// /// -// /// Gets all registered WebHooks for a given user. -// /// -// /// A collection containing the registered instances for a given user. -// [HttpGet] -// [Route("/api/webhooks/registrations")] -// [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// [GetRequestsErrorInterceptorActionFilter] -// public async Task> GetAllWebHooks() -// { -// string userId = GetUserId(); -// IEnumerable webHooks = await _store.GetAllWebHooksAsync(userId); -// RemovePrivateFilters(webHooks); -// return webHooks; -// } - -// /// -// /// Looks up a registered WebHook with the given for a given user. -// /// -// /// The registered instance for a given user. -// [HttpGet] -// [Route("/api/webhooks/registrations/{id}",Name = WebHookNames.GetWebhookByIdAction)] -// [ProducesResponseType(typeof(WebHook), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// [GetRequestsErrorInterceptorActionFilter] -// public async Task GetWebHookById(string id) -// { -// string userId = GetUserId(); -// WebHook webHook = await _store.LookupWebHookAsync(userId, id); -// if (webHook != null) -// { -// RemovePrivateFilters(new[] { webHook }); -// return Ok(webHook); -// } - -// return NotFound(); -// } - -// /// -// /// Registers a new WebHook for a given user. -// /// -// /// The to create. -// [HttpPost] -// [Route("/api/webhooks/registrations")] -// [ProducesResponseType(typeof(StoreResult), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] -// [ProducesResponseType(typeof(HttpResponseMessage), (int)HttpStatusCode.InternalServerError)] -// [ProducesResponseType(typeof(HttpResponseMessage), (int)HttpStatusCode.Conflict)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// public async Task RegisterWebHook([FromBody]WebHook webHook) -// { -// if (!ModelState.IsValid) -// { -// return Error(); -// } - -// if (webHook == null) -// { -// return BadRequest(); -// } - -// string userId = GetUserId(); - -// try -// { -// await VerifyFilters(webHook); -// await VerifyWebHook(webHook); -// } -// catch (VerificationException ex) -// { -// return BadRequest(ex.Message); -// } - -// // In order to ensure that a web hook filter is not registered multiple times for the same uri -// // we remove the already registered filters from the current web hook. -// // If the same filters are registered multiple times with the same uri, the web hook event will be -// // sent for each registration. -// IEnumerable existingWebhooks = await GetAllWebHooks(); -// IEnumerable existingWebhooksForTheSameUri = existingWebhooks.Where(wh => wh.WebHookUri == webHook.WebHookUri); - -// foreach (var existingWebHook in existingWebhooksForTheSameUri) -// { -// webHook.Filters.ExceptWith(existingWebHook.Filters); - -// if (!webHook.Filters.Any()) -// { -// string msg = _localizationService.GetResource("Api.WebHooks.CouldNotRegisterDuplicateWebhook"); -// return Error(HttpStatusCode.Conflict, ErrorPropertyKey, msg); -// } -// } - -// try -// { -// // Validate the provided WebHook ID (or force one to be created on server side) -// if (Request == null) -// { -// throw new ArgumentNullException(nameof(Request)); -// } - -// // Ensure we have a normalized ID for the WebHook -// webHook.Id = null; - -// // Add WebHook for this user. -// StoreResult result = await _store.InsertWebHookAsync(userId, webHook); - -// if (result == StoreResult.Success) -// { -// return CreatedAtRoute(WebHookNames.GetWebhookByIdAction, new { id = webHook.Id }, webHook); -// } -// return CreateHttpResult(result); -// } -// catch (Exception ex) -// { -// string msg = string.Format(CultureInfo.InvariantCulture, _localizationService.GetResource("Api.WebHooks.CouldNotRegisterWebhook"), ex.Message); -// //Configuration.DependencyResolver.GetLogger().Error(msg, ex); -// return Error(HttpStatusCode.Conflict, ErrorPropertyKey, msg); -// } -// } - -// /// -// /// Updates an existing WebHook registration. -// /// -// /// The WebHook ID. -// /// The new to use. -// [HttpPut] -// [Route("/api/webhooks/registrations/{id}")] -// [ProducesResponseType(typeof(StoreResult), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)] -// [ProducesResponseType(typeof(HttpResponseMessage), (int)HttpStatusCode.InternalServerError)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)] -// public async Task UpdateWebHook(string id, WebHook webHook) -// { -// if (webHook == null) -// { -// return BadRequest(); -// } -// if (!string.Equals(id, webHook.Id, StringComparison.OrdinalIgnoreCase)) -// { -// return BadRequest(); -// } - -// string userId = GetUserId(); -// await VerifyFilters(webHook); -// await VerifyWebHook(webHook); - -// try -// { -// StoreResult result = await _store.UpdateWebHookAsync(userId, webHook); -// return CreateHttpResult(result); -// } -// catch (Exception ex) -// { -// string msg = string.Format(CultureInfo.InvariantCulture, _localizationService.GetResource("Api.WebHooks.CouldNotUpdateWebhook"), ex.Message); -// // Configuration.DependencyResolver.GetLogger().Error(msg, ex); -// return Error(HttpStatusCode.InternalServerError, ErrorPropertyKey, msg); -// } -// } - -// /// -// /// Deletes an existing WebHook registration. -// /// -// /// The WebHook ID. -// [HttpDelete] -// [Route("/api/webhooks/registrations/{id}")] -// [ProducesResponseType(typeof(StoreResult), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(HttpResponseMessage), (int)HttpStatusCode.InternalServerError)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// public async Task DeleteWebHook(string id) -// { -// string userId = GetUserId(); - -// try -// { -// StoreResult result = await _store.DeleteWebHookAsync(userId, id); -// return CreateHttpResult(result); -// } -// catch (Exception ex) -// { -// string msg = string.Format(CultureInfo.InvariantCulture, _localizationService.GetResource("Api.WebHooks.CouldNotDeleteWebhook"), ex.Message); -// //Configuration.DependencyResolver.GetLogger().Error(msg, ex); -// return Error(HttpStatusCode.InternalServerError, ErrorPropertyKey, msg); -// } -// } - -// /// -// /// Deletes all existing WebHook registrations. -// /// -// [HttpDelete] -// [Route("/api/webhooks/registrations")] -// [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] -// [ProducesResponseType(typeof(HttpResponseMessage), (int)HttpStatusCode.InternalServerError)] -// [ProducesResponseType(typeof(string), (int)HttpStatusCode.Unauthorized)] -// public async Task DeleteAllWebHooks() -// { -// string userId = GetUserId(); - -// try -// { -// await _store.DeleteAllWebHooksAsync(userId); -// return Ok(); -// } -// catch (Exception ex) -// { -// string msg = string.Format(CultureInfo.InvariantCulture, _localizationService.GetResource("Api.WebHooks.CouldNotDeleteWebhooks"), ex.Message); -// // Configuration.DependencyResolver.GetLogger().Error(msg, ex); -// return Error(HttpStatusCode.InternalServerError, ErrorPropertyKey, msg); -// } -// } - -// /// -// /// Ensure that the provided only has registered filters. -// /// -// protected virtual async Task VerifyFilters(WebHook webHook) -// { -// if (webHook == null) -// { -// throw new ArgumentNullException(nameof(webHook)); -// } - -// // If there are no filters then add our wildcard filter. -// if (webHook.Filters.Count == 0) -// { -// webHook.Filters.Add(WildcardWebHookFilterProvider.Name); -// return; -// } - -// IDictionary filters = await _filterManager.GetAllWebHookFiltersAsync(); -// HashSet normalizedFilters = new HashSet(); -// List invalidFilters = new List(); -// foreach (string filter in webHook.Filters) -// { -// WebHookFilter hookFilter; -// if (filters.TryGetValue(filter, out hookFilter)) -// { -// normalizedFilters.Add(hookFilter.Name); -// } -// else -// { -// invalidFilters.Add(filter); -// } -// } - -// if (invalidFilters.Count > 0) -// { -// string invalidFiltersMsg = string.Join(", ", invalidFilters); -// string link = Url.Link(WebHookNames.FiltersGetAction, null); -// string msg = string.Format(CultureInfo.CurrentCulture, _localizationService.GetResource("Api.WebHooks.InvalidFilters"), invalidFiltersMsg, link); -// //Configuration.DependencyResolver.GetLogger().Info(msg); - -// throw new VerificationException(msg); -// } -// else -// { -// webHook.Filters.Clear(); -// foreach (string filter in normalizedFilters) -// { -// webHook.Filters.Add(filter); -// } -// } -// } - -// /// -// /// Removes all private filters from registered WebHooks. -// /// -// protected virtual void RemovePrivateFilters(IEnumerable webHooks) -// { -// if (webHooks == null) -// { -// throw new ArgumentNullException(nameof(webHooks)); -// } - -// foreach (WebHook webHook in webHooks) -// { -// var filters = webHook.Filters.Where(f => f.StartsWith(PRIVATE_FILTER_PREFIX, StringComparison.OrdinalIgnoreCase)).ToArray(); -// foreach (string filter in filters) -// { -// webHook.Filters.Remove(filter); -// } -// } -// } - -// /// -// /// Ensures that the provided has a reachable Web Hook URI unless -// /// the WebHook URI has a NoEcho query parameter. -// /// -// private async Task VerifyWebHook(WebHook webHook) -// { -// if (webHook == null) -// { -// throw new ArgumentNullException(nameof(webHook)); -// } - -// // If no secret is provided then we create one here. This allows for scenarios -// // where the caller may use a secret directly embedded in the WebHook URI, or -// // has some other way of enforcing security. -// if (string.IsNullOrEmpty(webHook.Secret)) -// { -// webHook.Secret = Guid.NewGuid().ToString("N"); -// } - -// try -// { -// await _manager.VerifyWebHookAsync(webHook); -// } -// catch (Exception ex) -// { -// throw new VerificationException(ex.Message); -// } -// } - -// /// -// /// Gets the user ID for this request. -// /// -// private string GetUserId() -// { -// // If we are here the client is already authorized. -// // So there is a client ID and the client is active. -// var clientId = -// _httpContextAccessor.HttpContext.User.FindFirst("client_id")?.Value; - -// var storeId = _storeContext.CurrentStore.Id; - -// var webHookUser = clientId + "-" + storeId; - -// return webHookUser; -// } - -// /// -// /// Creates an based on the provided . -// /// -// /// The result to use when creating the . -// /// An initialized . -// private IActionResult CreateHttpResult(StoreResult result) -// { -// switch (result) -// { -// case StoreResult.Success: -// return Ok(); - -// case StoreResult.Conflict: -// return Error(HttpStatusCode.Conflict); - -// case StoreResult.NotFound: -// return NotFound(); - -// case StoreResult.OperationError: -// return BadRequest(); - -// default: -// return Error(HttpStatusCode.InternalServerError); -// } -// } -// } -//} diff --git a/Nop.Plugin.Api/Data/ApiObjectContext.cs b/Nop.Plugin.Api/Data/ApiObjectContext.cs deleted file mode 100644 index d229c57..0000000 --- a/Nop.Plugin.Api/Data/ApiObjectContext.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -//using System.Data.Entity.Infrastructure; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Nop.Core; -using Nop.Data; -using Nop.Data.Extensions; -using Nop.Plugin.Api.DataMappings; - -namespace Nop.Plugin.Api.Data -{ - public class ApiObjectContext : DbContext, IDbContext - { - public ApiObjectContext(DbContextOptions options) - : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.ApplyConfiguration(new WebHooksMap()); - - //disable EdmMetadata generation - //modelBuilder.Conventions.Remove(); - base.OnModelCreating(modelBuilder); - } - - //TODO: Upgrade 4.10 Check this! - //public string CreateDatabaseScript() - //{ - // return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript(); - //} - - /// - /// Install - /// - public void Install() - { - //TODO: Upgrade 4.10 Check this! - //create the table - //var dbScript = CreateDatabaseScript(); - //Database.ExecuteSqlCommand(dbScript); - SaveChanges(); - } - - /// - /// Uninstall - /// - public void Uninstall() - { - this.DropPluginTable(nameof(Domain.WebHooks)); - } - - /// - /// Creates a DbSet that can be used to query and save instances of entity - /// - /// Entity type - /// A set for the given entity type - public virtual new DbSet Set() where TEntity : BaseEntity - { - return base.Set(); - } - - /// - /// Generate a script to create all tables for the current model - /// - /// A SQL script - public virtual string GenerateCreateScript() - { - return this.Database.GenerateCreateScript(); - } - - /// - /// Creates a LINQ query for the query type based on a raw SQL query - /// - /// Query type - /// The raw SQL query - /// An IQueryable representing the raw SQL query - public virtual IQueryable QueryFromSql(string sql) where TQuery : class - { - throw new NotImplementedException(); - } - - /// - /// Creates a LINQ query for the entity based on a raw SQL query - /// - /// Entity type - /// The raw SQL query - /// The values to be assigned to parameters - /// An IQueryable representing the raw SQL query - public virtual IQueryable EntityFromSql(string sql, params object[] parameters) where TEntity : BaseEntity - { - throw new NotImplementedException(); - } - - /// - /// Executes the given SQL against the database - /// - /// The SQL to execute - /// true - the transaction creation is not ensured; false - the transaction creation is ensured. - /// The timeout to use for command. Note that the command timeout is distinct from the connection timeout, which is commonly set on the database connection string - /// Parameters to use with the SQL - /// The number of rows affected - public virtual int ExecuteSqlCommand(RawSqlString sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters) - { - using (var transaction = this.Database.BeginTransaction()) - { - var result = this.Database.ExecuteSqlCommand(sql, parameters); - transaction.Commit(); - - return result; - } - } - - /// - /// Detach an entity from the context - /// - /// Entity type - /// Entity - public virtual void Detach(TEntity entity) where TEntity : BaseEntity - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/DataMappings/WebHooksMap.cs b/Nop.Plugin.Api/DataMappings/WebHooksMap.cs deleted file mode 100644 index c7f3415..0000000 --- a/Nop.Plugin.Api/DataMappings/WebHooksMap.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Nop.Data.Mapping; - -namespace Nop.Plugin.Api.DataMappings -{ - public class WebHooksMap : NopEntityTypeConfiguration - { - public override void Configure(EntityTypeBuilder builder) - { - builder.ToTable("WebHooks", "WebHooks"); - builder.HasKey(wh => new { wh.User, wh.Id }); - - builder.Property(wh => wh.ProtectedData).IsRequired(); - builder.Property(wh => wh.RowVer).IsRowVersion(); - } - } -} diff --git a/Nop.Plugin.Api/Domain/ApiSettings.cs b/Nop.Plugin.Api/Domain/ApiSettings.cs deleted file mode 100644 index 1075e52..0000000 --- a/Nop.Plugin.Api/Domain/ApiSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Nop.Core.Configuration; - -namespace Nop.Plugin.Api.Domain -{ - public class ApiSettings : ISettings - { - public bool EnableApi { get; set; } - public bool AllowRequestsFromSwagger { get; set; } - public bool EnableLogging { get; set; } - } -} \ No newline at end of file diff --git "a/Nop.Plugin.Api/Helpers/NopConfigMan\320\260gerHelper.cs" "b/Nop.Plugin.Api/Helpers/NopConfigMan\320\260gerHelper.cs" deleted file mode 100644 index d64d498..0000000 --- "a/Nop.Plugin.Api/Helpers/NopConfigMan\320\260gerHelper.cs" +++ /dev/null @@ -1,189 +0,0 @@ -using System.Xml.Linq; -using Nop.Core.Data; - -namespace Nop.Plugin.Api.Helpers -{ - using System; - using System.Reflection; - using System.Xml; - using System.Xml.XPath; - - public class NopConfigManagerHelper : IConfigManagerHelper - { - public NopConfigManagerHelper(DataSettings dataSettings) - { - DataSettings = dataSettings; - } - - public NopConfigManagerHelper() - { - DataSettings = DataSettingsManager.LoadSettings(); - } - - public void AddBindingRedirects() - { - var hasChanged = false; - - // load Nop.Web.exe.config - XDocument appConfig = null; - - var nopWebAssemblyConfigLocation = $"{Assembly.GetEntryAssembly().Location}.config"; - - using (var fs = System.IO.File.OpenRead(nopWebAssemblyConfigLocation)) - { - appConfig = XDocument.Load(fs); - } - - if (appConfig != null) - { - appConfig.Changed += (o, e) => { hasChanged = true; }; - - var runtime = appConfig.XPathSelectElement("configuration//runtime"); - - if (runtime == null) - { - runtime = new XElement("runtime"); - appConfig.XPathSelectElement("configuration")?.Add(runtime); - } - - // Required by Swagger - //AddAssemblyBinding(runtime, "Microsoft.AspNetCore.StaticFiles", "adb9793829ddae60", "0.0.0.0-2.0.0.0", "2.0.0.0"); - //AddAssemblyBinding(runtime, "Microsoft.Extensions.FileProviders.Embedded", "adb9793829ddae60", "0.0.0.0-2.0.0.0", "2.0.0.0"); - //AddAssemblyBinding(runtime, "Microsoft.AspNetCore.Mvc.Formatters.Json", "adb9793829ddae60", "0.0.0.0-2.0.0.0", "2.0.0.0"); - - // Required by WebHooks - AddAssemblyBinding(runtime, "Microsoft.AspNetCore.DataProtection.Abstractions", "adb9793829ddae60", "0.0.0.0-2.0.0.0", "2.0.0.0"); - - if (hasChanged) - { - // only save when changes have been made - try - { - appConfig.Save(nopWebAssemblyConfigLocation); - - //TODO: Upgrade 4.10 Check this! - //System.Configuration.ConfigurationManager.RefreshSection("runtime"); - } - catch (Exception) - { - // we should do nothing here as throwing an exception breaks nopCommerce. - // The right thing to do is to write a message in the Log that the user needs to provide Write access to Web.config - // but doing this will lead to many warnings in the Log added after each restart. - // So it is better to do nothing here. - //throw new NopException( - // "nopCommerce needs to be restarted due to a configuration change, but was unable to do so." + - // Environment.NewLine + - // "To prevent this issue in the future, a change to the web server configuration is required:" + - // Environment.NewLine + - // "- give the application write access to the 'web.config' file."); - } - } - } - } - - public DataSettings DataSettings { get; } - - public void AddConnectionString() - { - var hasChanged = false; - - // load web.config - XDocument appConfig = null; - - var nopWebAssemblyConfigLocation = $"{Assembly.GetEntryAssembly().Location}.config"; - - using (var fs = System.IO.File.OpenRead(nopWebAssemblyConfigLocation)) - { - appConfig = XDocument.Load(fs); - } - - if (appConfig != null) - { - appConfig.Changed += (o, e) => { hasChanged = true; }; - - var connectionStrings = appConfig.XPathSelectElement("configuration//connectionStrings"); - - if (connectionStrings == null) - { - var configuration = appConfig.XPathSelectElement("configuration"); - connectionStrings = new XElement("connectionStrings"); - configuration.Add(connectionStrings); - } - - var connectionStringFromNop = DataSettings.DataConnectionString; - - var element = appConfig.XPathSelectElement("configuration//connectionStrings//add[@name='MS_SqlStoreConnectionString']"); - - // create the connection string if not exists - if (element == null) - { - element = new XElement("add"); - element.SetAttributeValue("name", "MS_SqlStoreConnectionString"); - element.SetAttributeValue("connectionString", connectionStringFromNop); - element.SetAttributeValue("providerName", "System.Data.SqlClient"); - connectionStrings.Add(element); - } - else - { - // Check if the connection string is changed. - // If so update the connection string in the config. - var connectionStringInConfig = element.Attribute("connectionString").Value; - - if (!String.Equals(connectionStringFromNop, connectionStringInConfig, StringComparison.InvariantCultureIgnoreCase)) - { - element.SetAttributeValue("connectionString", connectionStringFromNop); - } - } - - if (hasChanged) - { - // only save when changes have been made - try - { - appConfig.Save(nopWebAssemblyConfigLocation); - - //TODO: Upgrade 4.1. Check this! - //System.Configuration.ConfigurationManager.RefreshSection("connectionStrings"); - } - catch - { - // we should do nothing here as throwing an exception breaks nopCommerce. - // The right thing to do is to write a message in the Log that the user needs to provide Write access to Web.config - // but doing this will lead to many warnings in the Log added after each restart. - // So it is better to do nothing here. - //throw new NopException( - // "nopCommerce needs to be restarted due to a configuration change, but was unable to do so." + - // Environment.NewLine + - // "To prevent this issue in the future, a change to the web server configuration is required:" + - // Environment.NewLine + - // "- give the application write access to the 'web.config' file."); - } - } - } - } - - private void AddAssemblyBinding(XElement runtime, string name, string publicToken, string oldVersion, string newVersion) - { - var xmlNamespaceManager = new XmlNamespaceManager(new NameTable()); - xmlNamespaceManager.AddNamespace("bind", "urn:schemas-microsoft-com:asm.v1"); - - var assemblyBindingElement = runtime.XPathSelectElement( - $"bind:assemblyBinding//bind:dependentAssembly//bind:assemblyIdentity[@name='{name}']", xmlNamespaceManager); - - // create the binding redirect if it does not exist - if (assemblyBindingElement == null) - { - assemblyBindingElement = XElement.Parse($@" - - - - - - - "); - - runtime.Add(assemblyBindingElement); - } - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeCallbackEndpoint.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeCallbackEndpoint.cs deleted file mode 100644 index 3fe5995..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeCallbackEndpoint.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System.Net; - using System.Threading.Tasks; - using IdentityServer4.Endpoints.Results; - using IdentityServer4.Extensions; - using IdentityServer4.Hosting; - using IdentityServer4.Models; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Stores; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Http; - - public class AuthorizeCallbackEndpoint : AuthorizeEndpointBase - { - private readonly IConsentMessageStore _consentResponseStore; - - public AuthorizeCallbackEndpoint( - IEventService events, - IAuthorizeRequestValidator validator, - IAuthorizeInteractionResponseGenerator interactionGenerator, - IAuthorizeResponseGenerator authorizeResponseGenerator, - IUserSession userSession, - IConsentMessageStore consentResponseStore) : base(events, userSession, validator, authorizeResponseGenerator, interactionGenerator) - { - _consentResponseStore = consentResponseStore; - } - - public override async Task ProcessAsync(HttpContext context) - { - if (context.Request.Method != "GET") - { - return new StatusCodeResult(HttpStatusCode.MethodNotAllowed); - } - - var parameters = context.Request.Query.AsNameValueCollection(); - - var user = await UserSession.GetUserAsync(); - var consentRequest = new ConsentRequest(parameters, user?.GetSubjectId()); - var consent = await _consentResponseStore.ReadAsync(consentRequest.Id); - - if (consent != null && consent.Data == null) - { - return await CreateErrorResultAsync("consent message is missing data"); - } - - try - { - var result = await ProcessAuthorizeRequestAsync(parameters, user, consent?.Data); - - return result; - } - finally - { - if (consent != null) - { - await _consentResponseStore.DeleteAsync(consentRequest.Id); - } - } - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpoint.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpoint.cs deleted file mode 100644 index b331710..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpoint.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System.Collections.Specialized; - using System.Net; - using System.Threading.Tasks; - using IdentityServer4.Endpoints.Results; - using IdentityServer4.Hosting; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Http; - - public class AuthorizeEndpoint : AuthorizeEndpointBase - { - public AuthorizeEndpoint( - IEventService events, - IAuthorizeRequestValidator validator, - IAuthorizeInteractionResponseGenerator interactionGenerator, - IAuthorizeResponseGenerator authorizeResponseGenerator, - IUserSession userSession) - : base(events, userSession, validator, authorizeResponseGenerator, interactionGenerator) - { - } - - public override async Task ProcessAsync(HttpContext context) - { - NameValueCollection values; - - if (context.Request.Method == "GET") - { - values = context.Request.Query.AsNameValueCollection(); - } - else if (context.Request.Method == "POST") - { - if (!context.Request.HasFormContentType) - { - return new StatusCodeResult(HttpStatusCode.UnsupportedMediaType); - } - - values = context.Request.Form.AsNameValueCollection(); - } - else - { - return new StatusCodeResult(HttpStatusCode.MethodNotAllowed); - } - - var user = await UserSession.GetUserAsync(); - var result = await ProcessAuthorizeRequestAsync(values, user, null); - - return result; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpointBase.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpointBase.cs deleted file mode 100644 index 35fd26e..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeEndpointBase.cs +++ /dev/null @@ -1,125 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System.Collections.Specialized; - using System.Security.Claims; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4.Endpoints.Results; - using IdentityServer4.Events; - using IdentityServer4.Hosting; - using IdentityServer4.Models; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Http; - - public abstract class AuthorizeEndpointBase : IEndpointHandler - { - private readonly IEventService _events; - private readonly IAuthorizeRequestValidator _validator; - private readonly IAuthorizeResponseGenerator _authorizeResponseGenerator; - private readonly IAuthorizeInteractionResponseGenerator _interactionGenerator; - - protected IUserSession UserSession { get; private set; } - - protected AuthorizeEndpointBase(IEventService events, IUserSession userSession, IAuthorizeRequestValidator validator, IAuthorizeResponseGenerator authorizeResponseGenerator, IAuthorizeInteractionResponseGenerator interactionGenerator) - { - _events = events; - UserSession = userSession; - _validator = validator; - _authorizeResponseGenerator = authorizeResponseGenerator; - _interactionGenerator = interactionGenerator; - } - - protected async Task CreateErrorResultAsync( - string logMessage, - ValidatedAuthorizeRequest request = null, - string error = OidcConstants.AuthorizeErrors.ServerError, - string errorDescription = null) - { - await RaiseFailureEventAsync(request, error, errorDescription); - - return new AuthorizeResult(new AuthorizeResponse - { - Request = request, - Error = error, - ErrorDescription = errorDescription - }); - } - - public abstract Task ProcessAsync(HttpContext context); - - protected Task RaiseResponseEventAsync(AuthorizeResponse response) - { - if (!response.IsError) - { - return _events.RaiseAsync(new TokenIssuedSuccessEvent(response)); - } - else - { - return RaiseFailureEventAsync(response.Request, response.Error, response.ErrorDescription); - } - } - - protected Task RaiseFailureEventAsync(ValidatedAuthorizeRequest request, string error, string errorDescription) - { - return _events.RaiseAsync(new TokenIssuedFailureEvent(request, error, errorDescription)); - } - - protected async Task ProcessAuthorizeRequestAsync(NameValueCollection parameters, ClaimsPrincipal user, ConsentResponse consent) - { - // validate request - var result = await _validator.ValidateAsync(parameters, user); - if (result.IsError) - { - return await CreateErrorResultAsync( - "Request validation failed", - result.ValidatedRequest, - result.Error, - result.ErrorDescription); - } - - var request = result.ValidatedRequest; - - // determine user interaction - var interactionResult = await _interactionGenerator.ProcessInteractionAsync(request, consent); - if (interactionResult.IsError) - { - return await CreateErrorResultAsync("Interaction generator error", request, interactionResult.Error); - } - if (interactionResult.IsLogin) - { - return new LoginPageResult(request); - } - if (interactionResult.IsConsent) - { - return new ConsentPageResult(request); - } - if (interactionResult.IsRedirect) - { - return new CustomRedirectResult(request, interactionResult.RedirectUrl); - } - - var response = await _authorizeResponseGenerator.CreateResponseAsync(request); - - await RaiseResponseEventAsync(response); - - return new AuthorizeResult(response); - } - - protected async Task CreateErrorResultAsync( - ValidatedAuthorizeRequest request = null, - string error = OidcConstants.AuthorizeErrors.ServerError, - string errorDescription = null) - { - await RaiseFailureEventAsync(request, error, errorDescription); - - return new AuthorizeResult(new AuthorizeResponse - { - Request = request, - Error = error, - ErrorDescription = errorDescription - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResponseExtensions.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResponseExtensions.cs deleted file mode 100644 index c4ae808..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResponseExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using IdentityServer4.ResponseHandling; - using System.Collections.Specialized; - using Nop.Plugin.Api.IdentityServer.Extensions; - - public static class AuthorizeResponseExtensions - { - public static NameValueCollection ToNameValueCollection(this AuthorizeResponse response) - { - var collection = new NameValueCollection(); - - if (response.IsError) - { - if (response.Error.IsPresent()) - { - collection.Add("error", response.Error); - } - if (response.ErrorDescription.IsPresent()) - { - collection.Add("error_description", response.ErrorDescription); - } - } - else - { - if (response.Code.IsPresent()) - { - collection.Add("code", response.Code); - } - - if (response.IdentityToken.IsPresent()) - { - collection.Add("id_token", response.IdentityToken); - } - - if (response.AccessToken.IsPresent()) - { - collection.Add("access_token", response.AccessToken); - collection.Add("token_type", "Bearer"); - collection.Add("expires_in", response.AccessTokenLifetime.ToString()); - } - - if (response.Scope.IsPresent()) - { - collection.Add("scope", response.Scope); - } - } - - if (response.State.IsPresent()) - { - collection.Add("state", response.State); - } - - if (response.SessionState.IsPresent()) - { - collection.Add("session_state", response.SessionState); - } - - return collection; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResult.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResult.cs deleted file mode 100644 index 86a823e..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/AuthorizeResult.cs +++ /dev/null @@ -1,198 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4.Configuration; - using IdentityServer4.Hosting; - using IdentityServer4.Models; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Stores; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.DependencyInjection; - using Nop.Plugin.Api.IdentityServer.Extensions; - - public class AuthorizeResult : IEndpointResult - { - public AuthorizeResponse Response { get; } - - public AuthorizeResult(AuthorizeResponse response) - { - Response = response ?? throw new ArgumentNullException(nameof(response)); - } - - internal AuthorizeResult( - AuthorizeResponse response, - IdentityServerOptions options, - IUserSession userSession, - IMessageStore errorMessageStore, - ISystemClock clock) - : this(response) - { - _options = options; - _userSession = userSession; - _errorMessageStore = errorMessageStore; - _clock = clock; - } - - private IdentityServerOptions _options; - private IUserSession _userSession; - private IMessageStore _errorMessageStore; - private ISystemClock _clock; - - private void Init(HttpContext context) - { - _options = _options ?? context.RequestServices.GetRequiredService(); - _userSession = _userSession ?? context.RequestServices.GetRequiredService(); - _errorMessageStore = _errorMessageStore ?? context.RequestServices.GetRequiredService>(); - _clock = _clock ?? context.RequestServices.GetRequiredService(); - } - - public async Task ExecuteAsync(HttpContext context) - { - Init(context); - - if (Response.IsError) - { - await ProcessErrorAsync(context); - } - else - { - await ProcessResponseAsync(context); - } - } - - private async Task ProcessErrorAsync(HttpContext context) - { - // these are the conditions where we can send a response - // back directly to the client, otherwise we're only showing the error UI - var isPromptNoneError = Response.Error == OidcConstants.AuthorizeErrors.AccountSelectionRequired || - Response.Error == OidcConstants.AuthorizeErrors.LoginRequired || - Response.Error == OidcConstants.AuthorizeErrors.ConsentRequired || - Response.Error == OidcConstants.AuthorizeErrors.InteractionRequired; - - if (Response.Error == OidcConstants.AuthorizeErrors.AccessDenied || - (isPromptNoneError && Response.Request?.PromptMode == OidcConstants.PromptModes.None) - ) - { - // this scenario we can return back to the client - await ProcessResponseAsync(context); - } - else - { - // we now know we must show error page - await RedirectToErrorPageAsync(context); - } - } - - protected async Task ProcessResponseAsync(HttpContext context) - { - if (!Response.IsError) - { - // success response -- track client authorization for sign-out - //_logger.LogDebug("Adding client {0} to client list cookie for subject {1}", request.ClientId, request.Subject.GetSubjectId()); - await _userSession.AddClientIdAsync(Response.Request.ClientId); - } - - await RenderAuthorizeResponseAsync(context); - } - - private async Task RenderAuthorizeResponseAsync(HttpContext context) - { - if (Response.Request.ResponseMode == OidcConstants.ResponseModes.Query || - Response.Request.ResponseMode == OidcConstants.ResponseModes.Fragment) - { - context.Response.SetNoCache(); - context.Response.Redirect(BuildRedirectUri()); - } - else if (Response.Request.ResponseMode == OidcConstants.ResponseModes.FormPost) - { - context.Response.SetNoCache(); - AddSecurityHeaders(context); - await context.Response.WriteHtmlAsync(GetFormPostHtml()); - } - else - { - //_logger.LogError("Unsupported response mode."); - throw new InvalidOperationException("Unsupported response mode"); - } - } - - private void AddSecurityHeaders(HttpContext context) - { - var formOrigin = Response.Request.RedirectUri.GetOrigin(); - var csp = $"default-src 'none'; frame-ancestors {formOrigin}; form-action {formOrigin}; script-src 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY='; "; - - if (!context.Response.Headers.ContainsKey("Content-Security-Policy")) - { - context.Response.Headers.Add("Content-Security-Policy", csp); - } - - if (!context.Response.Headers.ContainsKey("X-Content-Security-Policy")) - { - context.Response.Headers.Add("X-Content-Security-Policy", csp); - } - - var referrer_policy = "no-referrer"; - if (!context.Response.Headers.ContainsKey("Referrer-Policy")) - { - context.Response.Headers.Add("Referrer-Policy", referrer_policy); - } - } - - private string BuildRedirectUri() - { - var uri = Response.RedirectUri; - var query = Response.ToNameValueCollection().ToQueryString(); - - if (Response.Request.ResponseMode == OidcConstants.ResponseModes.Query) - { - uri = uri.AddQueryString(query); - } - else - { - uri = uri.AddHashFragment(query); - } - - if (Response.IsError && !uri.Contains("#")) - { - // https://tools.ietf.org/html/draft-bradley-oauth-open-redirector-00 - uri += "#_=_"; - } - - return uri; - } - - private const string FormPostHtml = "{body}"; - - private string GetFormPostHtml() - { - var html = FormPostHtml; - - html = html.Replace("{uri}", Response.Request.RedirectUri); - html = html.Replace("{body}", Response.ToNameValueCollection().ToFormPost()); - - return html; - } - - private async Task RedirectToErrorPageAsync(HttpContext context) - { - var errorModel = new ErrorMessage - { - RequestId = context.TraceIdentifier, - Error = Response.Error, - ErrorDescription = Response.ErrorDescription - }; - - var message = new Message(errorModel, _clock.UtcNow.UtcDateTime); - var id = await _errorMessageStore.WriteAsync(message); - - var errorUrl = _options.UserInteraction.ErrorUrl; - - var url = errorUrl.AddQueryString(_options.UserInteraction.ErrorIdParameter, id); - context.Response.RedirectToAbsoluteUrl(url); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenEndpoint.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/TokenEndpoint.cs deleted file mode 100644 index 415fa14..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenEndpoint.cs +++ /dev/null @@ -1,97 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System.Collections.Generic; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4.Events; - using IdentityServer4.Hosting; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Http; - - public class TokenEndpoint : IEndpointHandler - { - private readonly IClientSecretValidator _clientValidator; - private readonly ITokenRequestValidator _requestValidator; - private readonly ITokenResponseGenerator _responseGenerator; - private readonly IEventService _events; - - /// - /// Initializes a new instance of the class. - /// - /// The client validator. - /// The request validator. - /// The response generator. - /// The events. - /// The logger. - public TokenEndpoint( - IClientSecretValidator clientValidator, - ITokenRequestValidator requestValidator, - ITokenResponseGenerator responseGenerator, - IEventService events) - { - _clientValidator = clientValidator; - _requestValidator = requestValidator; - _responseGenerator = responseGenerator; - _events = events; - } - - /// - /// Processes the request. - /// - /// The HTTP context. - /// - public async Task ProcessAsync(HttpContext context) - { - // validate HTTP - if (context.Request.Method != "POST" || !context.Request.HasFormContentType) - { - return Error(OidcConstants.TokenErrors.InvalidRequest); - } - - return await ProcessTokenRequestAsync(context); - } - - private async Task ProcessTokenRequestAsync(HttpContext context) - { - // validate client - var clientResult = await _clientValidator.ValidateAsync(context); - - if (clientResult.Client == null) - { - return Error(OidcConstants.TokenErrors.InvalidClient); - } - - // validate request - var form = (await context.Request.ReadFormAsync()).AsNameValueCollection(); - var requestResult = await _requestValidator.ValidateRequestAsync(form, clientResult); - - if (requestResult.IsError) - { - await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult)); - return Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse); - } - - // create response - var response = await _responseGenerator.ProcessAsync(requestResult); - - await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult)); - - // return result - return new TokenResult(response); - } - - private TokenErrorResult Error(string error, string errorDescription = null, Dictionary custom = null) - { - var response = new TokenErrorResponse - { - Error = error, - ErrorDescription = errorDescription, - Custom = custom - }; - - return new TokenErrorResult(response); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenErrorResult.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/TokenErrorResult.cs deleted file mode 100644 index 42a2c17..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenErrorResult.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System; - using System.Threading.Tasks; - using IdentityServer4.Extensions; - using IdentityServer4.Hosting; - using IdentityServer4.ResponseHandling; - using Microsoft.AspNetCore.Http; - using Nop.Plugin.Api.IdentityServer.Extensions; - using Nop.Plugin.Api.IdentityServer.Infrastructure; - - public class TokenErrorResult : IEndpointResult - { - public TokenErrorResponse Response { get; } - - public TokenErrorResult(TokenErrorResponse error) - { - if (error.Error.IsMissing()) throw new ArgumentNullException("Error must be set", nameof(error.Error)); - - Response = error; - } - - public async Task ExecuteAsync(HttpContext context) - { - context.Response.StatusCode = 400; - context.Response.SetNoCache(); - - var dto = new ResultDto - { - error = Response.Error, - error_description = Response.ErrorDescription - }; - - if (Response.Custom.IsNullOrEmpty()) - { - await context.Response.WriteJsonAsync(dto); - } - else - { - var jobject = ObjectSerializer.ToJObject(dto); - jobject.AddDictionary(Response.Custom); - - await context.Response.WriteJsonAsync(jobject); - } - } - - internal class ResultDto - { - public string error { get; set; } - public string error_description { get; set; } - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenResult.cs b/Nop.Plugin.Api/IdentityServer/Endpoints/TokenResult.cs deleted file mode 100644 index 3598a12..0000000 --- a/Nop.Plugin.Api/IdentityServer/Endpoints/TokenResult.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Endpoints -{ - using System; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4.Extensions; - using IdentityServer4.Hosting; - using IdentityServer4.ResponseHandling; - using Microsoft.AspNetCore.Http; - using Nop.Plugin.Api.IdentityServer.Infrastructure; - - public class TokenResult : IEndpointResult - { - public TokenResponse Response { get; set; } - - public TokenResult(TokenResponse response) - { - if (response == null) throw new ArgumentNullException(nameof(response)); - - Response = response; - } - - public async Task ExecuteAsync(HttpContext context) - { - context.Response.SetNoCache(); - - var dto = new ResultDto - { - id_token = Response.IdentityToken, - access_token = Response.AccessToken, - refresh_token = Response.RefreshToken, - expires_in = Response.AccessTokenLifetime, - token_type = OidcConstants.TokenResponse.BearerTokenType - }; - - if (Response.Custom.IsNullOrEmpty()) - { - await context.Response.WriteJsonAsync(dto); - } - else - { - var jobject = ObjectSerializer.ToJObject(dto); - jobject.AddDictionary(Response.Custom); - - await context.Response.WriteJsonAsync(jobject); - } - } - - internal class ResultDto - { - public string id_token { get; set; } - public string access_token { get; set; } - public int expires_in { get; set; } - public string token_type { get; set; } - public string refresh_token { get; set; } - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Extensions/NameValueCollectionExtensions.cs b/Nop.Plugin.Api/IdentityServer/Extensions/NameValueCollectionExtensions.cs deleted file mode 100644 index 9452d0a..0000000 --- a/Nop.Plugin.Api/IdentityServer/Extensions/NameValueCollectionExtensions.cs +++ /dev/null @@ -1,143 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Extensions -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Linq; - using System.Text; - using System.Text.Encodings.Web; - - public static class NameValueCollectionExtensions - { - public static string ToQueryString(this NameValueCollection collection) - { - if (collection.Count == 0) - { - return String.Empty; - } - - var builder = new StringBuilder(128); - var first = true; - foreach (string name in collection) - { - var values = collection.GetValues(name); - if (values == null || values.Length == 0) - { - first = AppendNameValuePair(builder, first, true, name, String.Empty); - } - else - { - foreach (var value in values) - { - first = AppendNameValuePair(builder, first, true, name, value); - } - } - } - - return builder.ToString(); - } - - public static string ToFormPost(this NameValueCollection collection) - { - var builder = new StringBuilder(128); - const string inputFieldFormat = "\n"; - - foreach (string name in collection) - { - var values = collection.GetValues(name); - var value = values.First(); - value = HtmlEncoder.Default.Encode(value); - builder.AppendFormat(inputFieldFormat, name, value); - } - - return builder.ToString(); - } - - public static NameValueCollection ToNameValueCollection(this Dictionary data) - { - var result = new NameValueCollection(); - - if (data == null || data.Count == 0) - { - return result; - } - - foreach (var name in data.Keys) - { - var value = data[name]; - if (value != null) - { - result.Add(name, value); - } - } - - return result; - } - - public static Dictionary ToDictionary(this NameValueCollection collection) - { - return collection.ToScrubbedDictionary(); - } - - public static Dictionary ToScrubbedDictionary(this NameValueCollection collection, params string[] nameFilter) - { - var dict = new Dictionary(); - - if (collection == null || collection.Count == 0) - { - return dict; - } - - foreach (string name in collection) - { - var value = collection.Get(name); - if (value != null) - { - if (nameFilter.Contains(name)) - { - value = "***REDACTED***"; - } - dict.Add(name, value); - } - } - - return dict; - } - - internal static string ConvertFormUrlEncodedSpacesToUrlEncodedSpaces(string str) - { - if ((str != null) && (str.IndexOf('+') >= 0)) - { - str = str.Replace("+", "%20"); - } - return str; - } - - private static bool AppendNameValuePair(StringBuilder builder, bool first, bool urlEncode, string name, string value) - { - var effectiveName = name ?? String.Empty; - var encodedName = urlEncode ? UrlEncoder.Default.Encode(effectiveName) : effectiveName; - - var effectiveValue = value ?? String.Empty; - var encodedValue = urlEncode ? UrlEncoder.Default.Encode(effectiveValue) : effectiveValue; - encodedValue = ConvertFormUrlEncodedSpacesToUrlEncodedSpaces(encodedValue); - - if (first) - { - first = false; - } - else - { - builder.Append("&"); - } - - builder.Append(encodedName); - if (!String.IsNullOrEmpty(encodedValue)) - { - builder.Append("="); - builder.Append(encodedValue); - } - return first; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Extensions/StringsExtensions.cs b/Nop.Plugin.Api/IdentityServer/Extensions/StringsExtensions.cs deleted file mode 100644 index 8875385..0000000 --- a/Nop.Plugin.Api/IdentityServer/Extensions/StringsExtensions.cs +++ /dev/null @@ -1,222 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Extensions -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Diagnostics; - using System.Linq; - using System.Text; - using System.Text.Encodings.Web; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.WebUtilities; - - internal static class StringExtensions - { - [DebuggerStepThrough] - public static string ToSpaceSeparatedString(this IEnumerable list) - { - if (list == null) - { - return ""; - } - - var sb = new StringBuilder(100); - - foreach (var element in list) - { - sb.Append(element + " "); - } - - return sb.ToString().Trim(); - } - - [DebuggerStepThrough] - public static IEnumerable FromSpaceSeparatedString(this string input) - { - input = input.Trim(); - return input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - } - - public static List ParseScopesString(this string scopes) - { - if (scopes.IsMissing()) - { - return null; - } - - scopes = scopes.Trim(); - var parsedScopes = scopes.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); - - if (parsedScopes.Any()) - { - parsedScopes.Sort(); - return parsedScopes; - } - - return null; - } - - [DebuggerStepThrough] - public static bool IsMissing(this string value) - { - return string.IsNullOrWhiteSpace(value); - } - - [DebuggerStepThrough] - public static bool IsMissingOrTooLong(this string value, int maxLength) - { - if (string.IsNullOrWhiteSpace(value)) - { - return true; - } - if (value.Length > maxLength) - { - return true; - } - - return false; - } - - [DebuggerStepThrough] - public static bool IsPresent(this string value) - { - return !string.IsNullOrWhiteSpace(value); - } - - [DebuggerStepThrough] - public static string EnsureLeadingSlash(this string url) - { - if (!url.StartsWith("/")) - { - return "/" + url; - } - - return url; - } - - [DebuggerStepThrough] - public static string EnsureTrailingSlash(this string url) - { - if (!url.EndsWith("/")) - { - return url + "/"; - } - - return url; - } - - [DebuggerStepThrough] - public static string RemoveLeadingSlash(this string url) - { - if (url != null && url.StartsWith("/")) - { - url = url.Substring(1); - } - - return url; - } - - [DebuggerStepThrough] - public static string RemoveTrailingSlash(this string url) - { - if (url != null && url.EndsWith("/")) - { - url = url.Substring(0, url.Length - 1); - } - - return url; - } - - [DebuggerStepThrough] - public static string CleanUrlPath(this string url) - { - if (String.IsNullOrWhiteSpace(url)) url = "/"; - - if (url != "/" && url.EndsWith("/")) - { - url = url.Substring(0, url.Length - 1); - } - - return url; - } - - [DebuggerStepThrough] - public static bool IsLocalUrl(this string url) - { - return - !String.IsNullOrEmpty(url) && - - // Allows "/" or "/foo" but not "//" or "/\". - ((url[0] == '/' && (url.Length == 1 || (url[1] != '/' && url[1] != '\\'))) || - - // Allows "~/" or "~/foo". - (url.Length > 1 && url[0] == '~' && url[1] == '/')); - } - - [DebuggerStepThrough] - public static string AddQueryString(this string url, string query) - { - if (!url.Contains("?")) - { - url += "?"; - } - else if (!url.EndsWith("&")) - { - url += "&"; - } - - return url + query; - } - - [DebuggerStepThrough] - public static string AddQueryString(this string url, string name, string value) - { - return url.AddQueryString(name + "=" + UrlEncoder.Default.Encode(value)); - } - - [DebuggerStepThrough] - public static string AddHashFragment(this string url, string query) - { - if (!url.Contains("#")) - { - url += "#"; - } - - return url + query; - } - - [DebuggerStepThrough] - public static NameValueCollection ReadQueryStringAsNameValueCollection(this string url) - { - if (url != null) - { - var idx = url.IndexOf('?'); - if (idx >= 0) - { - url = url.Substring(idx + 1); - } - var query = QueryHelpers.ParseNullableQuery(url); - if (query != null) - { - return query.AsNameValueCollection(); - } - } - - return new NameValueCollection(); - } - - public static string GetOrigin(this string url) - { - if (url != null) - { - var uri = new Uri(url); - if (uri.Scheme == "http" || uri.Scheme == "https") - { - return $"{uri.Scheme}://{uri.Authority}"; - } - } - - return null; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Generators/CustomAuthorizeInteractionResponseGenerator.cs b/Nop.Plugin.Api/IdentityServer/Generators/CustomAuthorizeInteractionResponseGenerator.cs deleted file mode 100644 index 34cfb7b..0000000 --- a/Nop.Plugin.Api/IdentityServer/Generators/CustomAuthorizeInteractionResponseGenerator.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace Nop.Plugin.Api.IdentityServer.Generators -{ - using System; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4; - using IdentityServer4.Extensions; - using IdentityServer4.Models; - using IdentityServer4.ResponseHandling; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.Logging; - using IAuthenticationService = Microsoft.AspNetCore.Authentication.IAuthenticationService; - - public class NopApiAuthorizeInteractionResponseGenerator : IAuthorizeInteractionResponseGenerator - { - /// - /// The logger. - /// - protected readonly ILogger Logger; - - /// - /// The consent service. - /// - protected readonly IConsentService Consent; - - /// - /// The profile service. - /// - protected readonly IProfileService Profile; - - /// - /// The clock - /// - protected readonly ISystemClock Clock; - - private readonly IHttpContextAccessor _httpContextAccessor; - - private readonly IAuthenticationService _authenticationService; - - /// - /// Initializes a new instance of the class. - /// - /// The clock. - /// The logger. - /// The consent. - /// The profile. - public NopApiAuthorizeInteractionResponseGenerator( - ISystemClock clock, - ILogger logger, - IConsentService consent, - IProfileService profile, IHttpContextAccessor httpContextAccessor, IAuthenticationService authenticationService) - { - Clock = clock; - Logger = logger; - Consent = consent; - Profile = profile; - _httpContextAccessor = httpContextAccessor; - _authenticationService = authenticationService; - } - - /// - /// Processes the interaction logic. - /// - /// The request. - /// The consent. - /// - public virtual async Task ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) - { - Logger.LogTrace("ProcessInteractionAsync"); - - if (consent != null && consent.Granted == false && request.Subject.IsAuthenticated() == false) - { - // special case when anonymous user has issued a deny prior to authenticating - Logger.LogInformation("Error: User denied consent"); - return new InteractionResponse - { - Error = OidcConstants.AuthorizeErrors.AccessDenied - }; - } - - var identityServerUser = new IdentityServerUser(request.ClientId) - { - DisplayName = request.Client.ClientName, - AdditionalClaims = request.ClientClaims, - AuthenticationTime = new DateTime?(DateTime.UtcNow) - }; - - request.Subject = identityServerUser.CreatePrincipal(); - - var authenticationProperties = new AuthenticationProperties - { - IsPersistent = true, - IssuedUtc = DateTime.UtcNow - }; - - await _httpContextAccessor.HttpContext.SignInAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme, request.Subject, authenticationProperties); - - var result = new InteractionResponse(); - - return result; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Infrastructure/ObjectSerializer.cs b/Nop.Plugin.Api/IdentityServer/Infrastructure/ObjectSerializer.cs deleted file mode 100644 index a056644..0000000 --- a/Nop.Plugin.Api/IdentityServer/Infrastructure/ObjectSerializer.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Infrastructure -{ - using IdentityServer4.Infrastructure; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - public class ObjectSerializer - { - private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings - { - DefaultValueHandling = DefaultValueHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore - }; - - private static readonly JsonSerializer Serializer = new JsonSerializer - { - DefaultValueHandling = DefaultValueHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore - }; - - static ObjectSerializer() - { - Settings.Converters.Add(new NameValueCollectionConverter()); - } - - public static string ToString(object o) - { - return JsonConvert.SerializeObject(o, Settings); - } - - public static T FromString(string value) - { - return JsonConvert.DeserializeObject(value, Settings); - } - - public static JObject ToJObject(object o) - { - return JObject.FromObject(o, Serializer); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Middlewares/IdentityServerScopeParameterMiddleware.cs b/Nop.Plugin.Api/IdentityServer/Middlewares/IdentityServerScopeParameterMiddleware.cs deleted file mode 100644 index 74ab622..0000000 --- a/Nop.Plugin.Api/IdentityServer/Middlewares/IdentityServerScopeParameterMiddleware.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Middlewares -{ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Internal; - using Microsoft.Extensions.Primitives; - - public class IdentityServerScopeParameterMiddleware - { - private readonly RequestDelegate _next; - - public IdentityServerScopeParameterMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext context) - { - if (context.Request.Path.Value.Equals("/connect/authorize", StringComparison.InvariantCultureIgnoreCase) || - context.Request.Path.Value.Equals("/oauth/authorize", StringComparison.InvariantCultureIgnoreCase)) - { - // Make sure we have "nop_api" and "offline_access" scope - - var queryValues = new Dictionary(); - - foreach (var item in context.Request.Query) - { - if (item.Key == "scope") - { - string scopeValue = item.Value; - - if (!scopeValue.Contains("nop_api offline_access")) - { - // add our scope instead since we don't support other scopes - queryValues.Add(item.Key, "nop_api offline_access"); - continue; - } - } - - queryValues.Add(item.Key, item.Value); - } - - if (!queryValues.ContainsKey("scope")) - { - // if no scope is specified we add it - queryValues.Add("scope", "nop_api offline_access"); - } - - var newQueryCollection = new QueryCollection(queryValues); - - context.Request.Query = newQueryCollection; - - } - - await _next(context); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/IdentityServer/Services/ProfileService.cs b/Nop.Plugin.Api/IdentityServer/Services/ProfileService.cs deleted file mode 100644 index 57c5069..0000000 --- a/Nop.Plugin.Api/IdentityServer/Services/ProfileService.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Nop.Plugin.Api.IdentityServer.Services -{ - using System.Linq; - using System.Threading.Tasks; - using IdentityServer4.Models; - using IdentityServer4.Services; - using Nop.Plugin.Api.Services; - - public class ProfileService : IProfileService - { - private readonly IClientService _clientService; - - public ProfileService(IClientService clientService) - { - _clientService = clientService; - } - - // TODO: test this - public Task GetProfileDataAsync(ProfileDataRequestContext context) - { - var sub = context.Subject.Claims.FirstOrDefault(x => x.Type == "sub"); - - var userId = 0; - - if (int.TryParse(sub?.Value, out userId)) - { - // TODO: do we need claims?? - //IdentityServer4.EntityFramework.Entities.Client client = _clientService.GetClientByClientId(userId.ToString()); - //context.IssuedClaims = context.Subject.Claims.ToList(); - //context.IssuedClaims.Add(new Claim(type: ClaimTypes.NameIdentifier, value: client.Id.ToString())); - //context.IssuedClaims.Add(new Claim(type: ClaimTypes.Name, value: client.ClientName)); - } - - return Task.CompletedTask; - } - - public Task IsActiveAsync(IsActiveContext context) - { - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/MappingExtensions/ClientMappings.cs b/Nop.Plugin.Api/MappingExtensions/ClientMappings.cs deleted file mode 100644 index 21ffa3f..0000000 --- a/Nop.Plugin.Api/MappingExtensions/ClientMappings.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Nop.Plugin.Api.AutoMapper; - -namespace Nop.Plugin.Api.MappingExtensions -{ - using IdentityServer4.EntityFramework.Entities; - using Nop.Plugin.Api.Models; - - public static class ClientMappings - { - public static ClientApiModel ToApiModel(this Client client) - { - return client.MapTo(); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.Designer.cs b/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.Designer.cs deleted file mode 100644 index d5c3ca5..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.Designer.cs +++ /dev/null @@ -1,539 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.ConfigurationDb -{ - using System; - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Migrations; - - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20170319181717_Config")] - partial class Config - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiScopeId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri"); - - b.Property("LogoutSessionRequired"); - - b.Property("LogoutUri"); - - b.Property("PrefixClientClaims"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(2000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("IdentityResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiScopeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.cs b/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.cs deleted file mode 100644 index b098a63..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20170319181717_Config.cs +++ /dev/null @@ -1,500 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.ConfigurationDb -{ - using System; - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Migrations; - - public partial class Config : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApiResources", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Description = table.Column(maxLength: 1000, nullable: true), - DisplayName = table.Column(maxLength: 200, nullable: true), - Enabled = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Clients", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - AbsoluteRefreshTokenLifetime = table.Column(nullable: false), - AccessTokenLifetime = table.Column(nullable: false), - AccessTokenType = table.Column(nullable: false), - AllowAccessTokensViaBrowser = table.Column(nullable: false), - AllowOfflineAccess = table.Column(nullable: false), - AllowPlainTextPkce = table.Column(nullable: false), - AllowRememberConsent = table.Column(nullable: false), - AlwaysIncludeUserClaimsInIdToken = table.Column(nullable: false), - AlwaysSendClientClaims = table.Column(nullable: false), - AuthorizationCodeLifetime = table.Column(nullable: false), - ClientId = table.Column(maxLength: 200, nullable: false), - ClientName = table.Column(maxLength: 200, nullable: true), - ClientUri = table.Column(maxLength: 2000, nullable: true), - EnableLocalLogin = table.Column(nullable: false), - Enabled = table.Column(nullable: false), - IdentityTokenLifetime = table.Column(nullable: false), - IncludeJwtId = table.Column(nullable: false), - LogoUri = table.Column(nullable: true), - LogoutSessionRequired = table.Column(nullable: false), - LogoutUri = table.Column(nullable: true), - PrefixClientClaims = table.Column(nullable: false), - ProtocolType = table.Column(maxLength: 200, nullable: false), - RefreshTokenExpiration = table.Column(nullable: false), - RefreshTokenUsage = table.Column(nullable: false), - RequireClientSecret = table.Column(nullable: false), - RequireConsent = table.Column(nullable: false), - RequirePkce = table.Column(nullable: false), - SlidingRefreshTokenLifetime = table.Column(nullable: false), - UpdateAccessTokenClaimsOnRefresh = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Clients", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "IdentityResources", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Description = table.Column(maxLength: 1000, nullable: true), - DisplayName = table.Column(maxLength: 200, nullable: true), - Emphasize = table.Column(nullable: false), - Enabled = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false), - Required = table.Column(nullable: false), - ShowInDiscoveryDocument = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ApiClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(nullable: false), - Type = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiClaims_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(nullable: false), - Description = table.Column(maxLength: 1000, nullable: true), - DisplayName = table.Column(maxLength: 200, nullable: true), - Emphasize = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false), - Required = table.Column(nullable: false), - ShowInDiscoveryDocument = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopes", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopes_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiSecrets", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(nullable: false), - Description = table.Column(maxLength: 1000, nullable: true), - Expiration = table.Column(nullable: true), - Type = table.Column(maxLength: 250, nullable: true), - Value = table.Column(maxLength: 2000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - Type = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 250, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientClaims", x => x.Id); - table.ForeignKey( - name: "FK_ClientClaims_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientCorsOrigins", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - Origin = table.Column(maxLength: 150, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); - table.ForeignKey( - name: "FK_ClientCorsOrigins_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientGrantTypes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - GrantType = table.Column(maxLength: 250, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); - table.ForeignKey( - name: "FK_ClientGrantTypes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientIdPRestrictions", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - Provider = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); - table.ForeignKey( - name: "FK_ClientIdPRestrictions_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientPostLogoutRedirectUris", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - PostLogoutRedirectUri = table.Column(maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientRedirectUris", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - RedirectUri = table.Column(maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientScopes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - Scope = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientScopes", x => x.Id); - table.ForeignKey( - name: "FK_ClientScopes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientSecrets", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(nullable: false), - Description = table.Column(maxLength: 2000, nullable: true), - Expiration = table.Column(nullable: true), - Type = table.Column(maxLength: 250, nullable: true), - Value = table.Column(maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ClientSecrets_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - IdentityResourceId = table.Column(nullable: false), - Type = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopeClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ApiScopeId = table.Column(nullable: false), - Type = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", - column: x => x.ApiScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiResources_Name", - table: "ApiResources", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiClaims_ApiResourceId", - table: "ApiClaims", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_ApiResourceId", - table: "ApiScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_Name", - table: "ApiScopes", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ApiScopeId", - table: "ApiScopeClaims", - column: "ApiScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiSecrets_ApiResourceId", - table: "ApiSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_Clients_ClientId", - table: "Clients", - column: "ClientId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientSecrets_ClientId", - table: "ClientSecrets", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityClaims_IdentityResourceId", - table: "IdentityClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResources_Name", - table: "IdentityResources", - column: "Name", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiClaims"); - - migrationBuilder.DropTable( - name: "ApiScopeClaims"); - - migrationBuilder.DropTable( - name: "ApiSecrets"); - - migrationBuilder.DropTable( - name: "ClientClaims"); - - migrationBuilder.DropTable( - name: "ClientCorsOrigins"); - - migrationBuilder.DropTable( - name: "ClientGrantTypes"); - - migrationBuilder.DropTable( - name: "ClientIdPRestrictions"); - - migrationBuilder.DropTable( - name: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientScopes"); - - migrationBuilder.DropTable( - name: "ClientSecrets"); - - migrationBuilder.DropTable( - name: "IdentityClaims"); - - migrationBuilder.DropTable( - name: "ApiScopes"); - - migrationBuilder.DropTable( - name: "Clients"); - - migrationBuilder.DropTable( - name: "IdentityResources"); - - migrationBuilder.DropTable( - name: "ApiResources"); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.Designer.cs b/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.Designer.cs deleted file mode 100644 index b0b160e..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.Designer.cs +++ /dev/null @@ -1,590 +0,0 @@ -// - -namespace Nop.Plugin.Api.Migrations.IdentityServer.ConfigurationDb -{ - using System; - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Migrations; - - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20171107104928_DotNetCore2IdentityServerConfigurationDbMigration")] - partial class DotNetCore2IdentityServerConfigurationDbMigration - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.0.0-rtm-26452") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiScopeId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("BackChannelLogoutSessionRequired"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("ConsentLifetime"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("FrontChannelLogoutSessionRequired"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri") - .HasMaxLength(2000); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientProperties"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(2000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("IdentityResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiScopeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.cs b/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.cs deleted file mode 100644 index 3db8418..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/20171107104928_DotNetCore2IdentityServerConfigurationDbMigration.cs +++ /dev/null @@ -1,177 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.ConfigurationDb -{ - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Migrations; - - public partial class DotNetCore2IdentityServerConfigurationDbMigration : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "LogoutSessionRequired", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "LogoutUri", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PrefixClientClaims", - table: "Clients"); - - migrationBuilder.AlterColumn( - name: "LogoUri", - table: "Clients", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: true, - oldClrType: typeof(string), - oldNullable: true); - - migrationBuilder.AddColumn( - name: "BackChannelLogoutSessionRequired", - table: "Clients", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "BackChannelLogoutUri", - table: "Clients", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: true); - - migrationBuilder.AddColumn( - name: "ClientClaimsPrefix", - table: "Clients", - type: "nvarchar(200)", - maxLength: 200, - nullable: true); - - migrationBuilder.AddColumn( - name: "ConsentLifetime", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AddColumn( - name: "Description", - table: "Clients", - type: "nvarchar(1000)", - maxLength: 1000, - nullable: true); - - migrationBuilder.AddColumn( - name: "FrontChannelLogoutSessionRequired", - table: "Clients", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "FrontChannelLogoutUri", - table: "Clients", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: true); - - migrationBuilder.AddColumn( - name: "PairWiseSubjectSalt", - table: "Clients", - type: "nvarchar(200)", - maxLength: 200, - nullable: true); - - migrationBuilder.CreateTable( - name: "ClientProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientProperties", x => x.Id); - table.ForeignKey( - name: "FK_ClientProperties_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ClientProperties"); - - migrationBuilder.DropColumn( - name: "BackChannelLogoutSessionRequired", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "BackChannelLogoutUri", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "ClientClaimsPrefix", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "ConsentLifetime", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "Description", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "FrontChannelLogoutSessionRequired", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "FrontChannelLogoutUri", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PairWiseSubjectSalt", - table: "Clients"); - - migrationBuilder.AlterColumn( - name: "LogoUri", - table: "Clients", - nullable: true, - oldClrType: typeof(string), - oldType: "nvarchar(2000)", - oldMaxLength: 2000, - oldNullable: true); - - migrationBuilder.AddColumn( - name: "LogoutSessionRequired", - table: "Clients", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "LogoutUri", - table: "Clients", - nullable: true); - - migrationBuilder.AddColumn( - name: "PrefixClientClaims", - table: "Clients", - nullable: false, - defaultValue: false); - } - } -} diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs deleted file mode 100644 index 855cd9d..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs +++ /dev/null @@ -1,537 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.ConfigurationDb -{ - using System; - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Metadata; - - [DbContext(typeof(ConfigurationDbContext))] - partial class ConfigurationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiScopeId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiResourceId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri"); - - b.Property("LogoutSessionRequired"); - - b.Property("LogoutUri"); - - b.Property("PrefixClientClaims"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId") - .IsRequired(); - - b.Property("Description") - .HasMaxLength(2000); - - b.Property("Expiration"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("IdentityResourceId") - .IsRequired(); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiScopeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.Designer.cs b/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.Designer.cs deleted file mode 100644 index 097a742..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.Designer.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.PersitedGrantDb -{ - using System; - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Migrations; - - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20170319181710_Grants")] - partial class Grants - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000); - - b.Property("Expiration"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("PersistedGrants"); - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.cs b/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.cs deleted file mode 100644 index 0a053d7..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/20170319181710_Grants.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.PersitedGrantDb -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - public partial class Grants : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(maxLength: 200, nullable: false), - ClientId = table.Column(maxLength: 200, nullable: false), - CreationTime = table.Column(nullable: false), - Data = table.Column(maxLength: 50000, nullable: false), - Expiration = table.Column(nullable: true), - SubjectId = table.Column(maxLength: 200, nullable: true), - Type = table.Column(maxLength: 50, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PersistedGrants"); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/PersistedGrantDbContextModelSnapshot.cs b/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/PersistedGrantDbContextModelSnapshot.cs deleted file mode 100644 index d534f5a..0000000 --- a/Nop.Plugin.Api/Migrations/IdentityServer/PersitedGrantDb/PersistedGrantDbContextModelSnapshot.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Nop.Plugin.Api.Migrations.IdentityServer.PersitedGrantDb -{ - using System; - using IdentityServer4.EntityFramework.DbContexts; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Metadata; - - [DbContext(typeof(PersistedGrantDbContext))] - partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000); - - b.Property("Expiration"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("PersistedGrants"); - }); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Models/OrdersParameters/OrdersCountParametersModel.cs b/Nop.Plugin.Api/Models/OrdersParameters/OrdersCountParametersModel.cs deleted file mode 100644 index ca7985f..0000000 --- a/Nop.Plugin.Api/Models/OrdersParameters/OrdersCountParametersModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Nop.Plugin.Api.ModelBinders; - -namespace Nop.Plugin.Api.Models.OrdersParameters -{ - using Microsoft.AspNetCore.Mvc; - - [ModelBinder(typeof(ParametersModelBinder))] - public class OrdersCountParametersModel : BaseOrdersParametersModel - { - // Nothing special here, created just for clarity. - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Nop.Plugin.Api.csproj b/Nop.Plugin.Api/Nop.Plugin.Api.csproj deleted file mode 100644 index 02d59cb..0000000 --- a/Nop.Plugin.Api/Nop.Plugin.Api.csproj +++ /dev/null @@ -1,81 +0,0 @@ - - - - netcoreapp2.1 - This plugin allows you to access/create Nop resources outside of the system - true - - - - ..\..\Presentation\Nop.Web\Plugins\Nop.Plugin.Api - $(OutputPath) - true - - - - ..\..\Presentation\Nop.Web\Plugins\Nop.Plugin.Api - $(OutputPath) - true - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Nop.Plugin.Api/RouteProvider.cs b/Nop.Plugin.Api/RouteProvider.cs deleted file mode 100644 index d91ed59..0000000 --- a/Nop.Plugin.Api/RouteProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.AspNetCore.Routing; -using Nop.Web.Framework.Mvc.Routing; - -namespace Nop.Plugin.Api -{ - public class RouteProvider : IRouteProvider - { - public void RegisterRoutes(IRouteBuilder routeBuilder) - { - - } - - public int Priority => -1; - } -} diff --git a/Nop.Plugin.Api/Services/ClientService.cs b/Nop.Plugin.Api/Services/ClientService.cs deleted file mode 100644 index 5ef4644..0000000 --- a/Nop.Plugin.Api/Services/ClientService.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Nop.Plugin.Api.Services -{ - using IdentityModel; - using IdentityServer4; - using IdentityServer4.EntityFramework.Entities; - using IdentityServer4.EntityFramework.Interfaces; - using IdentityServer4.Models; - using Microsoft.EntityFrameworkCore; - using MappingExtensions; - using Models; - using Client = IdentityServer4.EntityFramework.Entities.Client; - - public class ClientService : IClientService - { - private readonly IConfigurationDbContext _configurationDbContext; - - public ClientService(IConfigurationDbContext configurationDbContext) - { - _configurationDbContext = configurationDbContext; - } - - public IList GetAllClients() - { - IQueryable clientsQuery = _configurationDbContext.Clients - .Include(x => x.ClientSecrets) - .Include(x => x.RedirectUris); - - IList clients = clientsQuery.ToList(); - - IList clientApiModels = clients.Select(client => client.ToApiModel()).ToList(); - - return clientApiModels; - } - - public int InsertClient(ClientApiModel model) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - - var client = new Client - { - ClientId = model.ClientId, - Enabled = model.Enabled, - ClientName = model.ClientName, - // Needed to be able to obtain refresh token. - AllowOfflineAccess = true, - AccessTokenLifetime = model.AccessTokenLifetime, - AbsoluteRefreshTokenLifetime = model.RefreshTokenLifetime - }; - - AddOrUpdateClientSecret(client, model.ClientSecret); - AddOrUpdateClientRedirectUrl(client, model.RedirectUrl); - - client.AllowedGrantTypes = new List - { - new ClientGrantType - { - Client = client, - GrantType = OidcConstants.GrantTypes.AuthorizationCode - }, - new ClientGrantType - { - Client = client, - GrantType = OidcConstants.GrantTypes.RefreshToken - }, - new ClientGrantType - { - Client = client, - GrantType = OidcConstants.GrantTypes.JwtBearer - } - }; - - client.AllowedScopes = new List - { - new ClientScope - { - Client = client, - Scope = "nop_api" - } - }; - - client.Claims = new List - { - new ClientClaim - { - Client = client, - Type = JwtClaimTypes.Subject, - Value = client.ClientId - }, - new ClientClaim - { - Client = client, - Type = JwtClaimTypes.Name, - Value = client.ClientName - } - - }; - - _configurationDbContext.Clients.Add(client); - _configurationDbContext.SaveChanges(); - - return client.Id; - } - - public void UpdateClient(ClientApiModel model) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - - var currentClient = _configurationDbContext.Clients - .Include(client => client.ClientSecrets) - .Include(client => client.RedirectUris) - .FirstOrDefault(client => client.ClientId == model.ClientId); - - if (currentClient == null) - { - throw new ArgumentNullException(nameof(currentClient)); - } - - AddOrUpdateClientSecret(currentClient, model.ClientSecret); - AddOrUpdateClientRedirectUrl(currentClient, model.RedirectUrl); - - currentClient.ClientId = model.ClientId; - currentClient.ClientName = model.ClientName; - currentClient.Enabled = model.Enabled; - currentClient.AccessTokenLifetime = model.AccessTokenLifetime; - currentClient.AbsoluteRefreshTokenLifetime = model.RefreshTokenLifetime; - - _configurationDbContext.Clients.Update(currentClient); - _configurationDbContext.SaveChanges(); - } - - public ClientApiModel FindClientByIdAsync(int id) - { - var currentClient = _configurationDbContext.Clients - .Include(client => client.ClientSecrets) - .Include(client => client.RedirectUris) - .FirstOrDefault(client => client.Id == id); - - return currentClient?.ToApiModel(); - } - - public ClientApiModel FindClientByClientId(string clientId) - { - var currentClient = _configurationDbContext.Clients - .Include(client => client.ClientSecrets) - .Include(client => client.RedirectUris) - .FirstOrDefault(client => client.ClientId == clientId); - - return currentClient?.ToApiModel(); - } - - public void DeleteClient(int id) - { - var client = _configurationDbContext.Clients - .Include(entity => entity.ClientSecrets) - .Include(entity => entity.RedirectUris) - .FirstOrDefault(x => x.Id == id); - - if (client != null) - { - _configurationDbContext.Clients.Remove(client); - _configurationDbContext.SaveChanges(); - } - } - - private void AddOrUpdateClientRedirectUrl(Client currentClient, string modelRedirectUrl) - { - // Ensure the client redirect url collection is not null - if (currentClient.RedirectUris == null) - { - currentClient.RedirectUris = new List(); - } - - // Currently, the api works with only one client redirect uri. - var currentClientRedirectUri = currentClient.RedirectUris.FirstOrDefault(); - - // Add new redirectUri - if ((currentClientRedirectUri != null && currentClientRedirectUri.RedirectUri != modelRedirectUrl) || - currentClientRedirectUri == null) - { - // Remove all redirect uris as we may have only one. - currentClient.RedirectUris.Clear(); - - currentClient.RedirectUris.Add(new ClientRedirectUri - { - Client = currentClient, - RedirectUri = modelRedirectUrl - }); - } - } - - private void AddOrUpdateClientSecret(Client currentClient, string modelClientSecretDescription) - { - // Ensure the client secrets collection is not null - if (currentClient.ClientSecrets == null) - { - currentClient.ClientSecrets = new List(); - } - - // Currently, the api works with only one client secret. - var currentClientSecret = currentClient.ClientSecrets.FirstOrDefault(); - - // Add new secret - if ((currentClientSecret != null && currentClientSecret.Description != modelClientSecretDescription) || - currentClientSecret == null) - { - // Remove all secrets as we may have only one valid. - currentClient.ClientSecrets.Clear(); - - currentClient.ClientSecrets.Add(new ClientSecret - { - Client = currentClient, - Value = modelClientSecretDescription.Sha256(), - Type = IdentityServerConstants.ParsedSecretTypes.SharedSecret, - Description = modelClientSecretDescription - }); - } - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/OrderItemApiService.cs b/Nop.Plugin.Api/Services/OrderItemApiService.cs deleted file mode 100644 index 9542535..0000000 --- a/Nop.Plugin.Api/Services/OrderItemApiService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DataStructures; - -namespace Nop.Plugin.Api.Services -{ - public class OrderItemApiService : IOrderItemApiService - { - public IList GetOrderItemsForOrder(Order order, int limit, int page, int sinceId) - { - var orderItems = order.OrderItems.AsQueryable(); - - return new ApiList(orderItems, page - 1, limit); - } - - public int GetOrderItemsCount(Order order) - { - var orderItemsCount = order.OrderItems.Count(); - - return orderItemsCount; - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/ClientValidator.cs b/Nop.Plugin.Api/Validators/ClientValidator.cs deleted file mode 100644 index 75e1db0..0000000 --- a/Nop.Plugin.Api/Validators/ClientValidator.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FluentValidation; -using Nop.Services.Localization; - -namespace Nop.Plugin.Api.Validators -{ - using IdentityServer4.Models; - - public class ClientValidator : AbstractValidator - { - public ClientValidator(ILocalizationService localizationService) - { - RuleFor(x => x.ClientName).NotEmpty().WithMessage(localizationService.GetResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.Name")); - RuleFor(x => x.ClientId).NotEmpty().WithMessage(localizationService.GetResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientId")); - RuleFor(x => x.ClientSecrets).NotEmpty().WithMessage(localizationService.GetResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.ClientSecret")); - RuleFor(x => x.RedirectUris).NotEmpty().WithMessage(localizationService.GetResource("Plugins.Api.Admin.Entities.Client.FieldValidationMessages.CallbackUrl")); - } - } -} \ No newline at end of file diff --git a/Nop.Plugin.Api/Views/Clients/ClientSettings.cshtml b/Nop.Plugin.Api/Views/Clients/ClientSettings.cshtml deleted file mode 100644 index 23f7d9d..0000000 --- a/Nop.Plugin.Api/Views/Clients/ClientSettings.cshtml +++ /dev/null @@ -1,76 +0,0 @@ -@model ClientApiModel - -
-
- -
-
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
-
-
-
\ No newline at end of file diff --git a/Nop.Plugin.Api/Views/Clients/Create.cshtml b/Nop.Plugin.Api/Views/Clients/Create.cshtml deleted file mode 100644 index a74e4f3..0000000 --- a/Nop.Plugin.Api/Views/Clients/Create.cshtml +++ /dev/null @@ -1,33 +0,0 @@ -@model ClientApiModel - -@{ - Layout = ViewNames.AdminLayout; - - //page title - ViewBag.Title = T("Plugins.Api.Admin.Page.Clients.Create.Title").Text; - //active menu item (system name) - Html.SetActiveMenuItemSystemName("Api-Clients-Menu"); -} - -
- @Html.AntiForgeryToken() - -
-

- @T("Plugins.Api.Admin.Page.Clients.Create.Title") - @Html.ActionLink(T("Plugins.Api.Admin.Client.BackToList").Text, "List") -

-
- - -
-
- - @await Html.PartialAsync(ViewNames.AdminApiClientsCreateOrUpdate, Model) -
\ No newline at end of file diff --git a/Nop.Plugin.Api/Views/Clients/CreateOrUpdate.cshtml b/Nop.Plugin.Api/Views/Clients/CreateOrUpdate.cshtml deleted file mode 100644 index 2a3f6ab..0000000 --- a/Nop.Plugin.Api/Views/Clients/CreateOrUpdate.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@model ClientApiModel - -
-
- @await Html.PartialAsync(ViewNames.AdminApiClientsSettings, Model) -
-
diff --git a/Nop.Plugin.Api/Views/Clients/Edit.cshtml b/Nop.Plugin.Api/Views/Clients/Edit.cshtml deleted file mode 100644 index 36f3629..0000000 --- a/Nop.Plugin.Api/Views/Clients/Edit.cshtml +++ /dev/null @@ -1,41 +0,0 @@ -@model ClientApiModel - -@{ - Layout = ViewNames.AdminLayout; - - //page title - ViewBag.Title = T("Plugins.Api.Admin.Page.Clients.Edit.Title").Text; - //active menu item (system name) - Html.SetActiveMenuItemSystemName("Api-Clients-Menu"); -} - -
- @Html.HiddenFor(model => model.Id) - @Html.AntiForgeryToken() - -
-

- @T("Plugins.Api.Admin.Page.Clients.Edit.Title") - @Model.ClientName - @Html.ActionLink(T("Plugins.Api.Admin.Client.BackToList").Text, "List") -

-
- - - - - @T("Admin.Common.Delete") - -
-
- - @await Html.PartialAsync(ViewNames.AdminApiClientsCreateOrUpdate, Model) - -
- - \ No newline at end of file diff --git a/Nop.Plugin.Api/Views/Clients/List.cshtml b/Nop.Plugin.Api/Views/Clients/List.cshtml deleted file mode 100644 index f2e9050..0000000 --- a/Nop.Plugin.Api/Views/Clients/List.cshtml +++ /dev/null @@ -1,100 +0,0 @@ -@{ - Layout = ViewNames.AdminLayout; - - //page title - ViewBag.Title = T("Plugins.Api.Admin.Page.Clients.Title").Text; - //active menu item (system name) - Html.SetActiveMenuItemSystemName("Api-Clients-Menu"); -} - -@Html.AntiForgeryToken() - -
-

- @T("Plugins.Api.Admin.Page.Clients.Title") -

- -
- -
-
-
-
-
-
- - -
-
-
-
-
\ No newline at end of file diff --git a/Nop.Plugin.Api/WebHooks/ApiWebHookSender.cs b/Nop.Plugin.Api/WebHooks/ApiWebHookSender.cs deleted file mode 100644 index 4a9761e..0000000 --- a/Nop.Plugin.Api/WebHooks/ApiWebHookSender.cs +++ /dev/null @@ -1,35 +0,0 @@ -//using System.Collections.Generic; -//using Newtonsoft.Json.Linq; - -//namespace Nop.Plugin.Api.WebHooks -//{ -// using Microsoft.AspNet.WebHooks; -// using Microsoft.AspNet.WebHooks.Diagnostics; - -// public class ApiWebHookSender : DataflowWebHookSender -// { -// private const string WebHookIdKey = "WebHookId"; - -// public ApiWebHookSender(ILogger logger) : base(logger) -// { -// } - -// /// -// protected override JObject CreateWebHookRequestBody(WebHookWorkItem workItem) -// { -// JObject data = base.CreateWebHookRequestBody(workItem); - -// Dictionary body = data.ToObject>(); - -// // The web hook id is added to the web hook body. -// // This is required in order to properly validate the web hook. -// // When a web hook is created, it is created with a Secred field. -// // The web hook id and the secret can be stored in the client's database, so that when a web hook is received -// // it can be validated with the secret in the database. -// // This ensures that the web hook is send from the proper location and that it's content were not tampered with. -// body[WebHookIdKey] = workItem.WebHook.Id; - -// return JObject.FromObject(body); -// } -// } -//} diff --git a/Nop.Plugin.Api/WebHooks/FilterProvider.cs b/Nop.Plugin.Api/WebHooks/FilterProvider.cs deleted file mode 100644 index 9f1f9ee..0000000 --- a/Nop.Plugin.Api/WebHooks/FilterProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -//using System.Collections.ObjectModel; -//using System.Threading.Tasks; -//using Nop.Plugin.Api.Constants; - -//namespace Nop.Plugin.Api.WebHooks -//{ -// using Microsoft.AspNet.WebHooks; - -// public class FilterProvider : IWebHookFilterProvider -// { -// private readonly Collection filters = new Collection -// { -// new WebHookFilter { Name = WebHookNames.CustomersCreate, Description = "A customer has been registered."}, -// new WebHookFilter { Name = WebHookNames.CustomersUpdate, Description = "A customer has been updated."}, -// new WebHookFilter { Name = WebHookNames.CustomersDelete, Description = "A customer has been deleted."}, -// new WebHookFilter { Name = WebHookNames.ProductsCreate, Description = "A product has been created."}, -// new WebHookFilter { Name = WebHookNames.ProductsUpdate, Description = "A product has been updated."}, -// new WebHookFilter { Name = WebHookNames.ProductsDelete, Description = "A product has been deleted."}, -// new WebHookFilter { Name = WebHookNames.ProductsUnmap, Description = "A product has been unmapped from the store."}, -// new WebHookFilter { Name = WebHookNames.CategoriesCreate, Description = "A category has been created."}, -// new WebHookFilter { Name = WebHookNames.CategoriesUpdate, Description = "A category has been updated."}, -// new WebHookFilter { Name = WebHookNames.CategoriesDelete, Description = "A category has been deleted."}, -// new WebHookFilter { Name = WebHookNames.CategoriesUnmap, Description = "A category has been unmapped from the store."}, -// new WebHookFilter { Name = WebHookNames.OrdersCreate, Description = "An order has been created."}, -// new WebHookFilter { Name = WebHookNames.OrdersUpdate, Description = "An order has been updated."}, -// new WebHookFilter { Name = WebHookNames.OrdersDelete, Description = "An order has been deleted."}, -// new WebHookFilter { Name = WebHookNames.ProductCategoryMapsCreate, Description = "A product category map has been created."}, -// new WebHookFilter { Name = WebHookNames.ProductCategoryMapsUpdate, Description = "A product category map has been updated."}, -// new WebHookFilter { Name = WebHookNames.ProductCategoryMapsDelete, Description = "A product category map has been deleted."}, -// new WebHookFilter { Name = WebHookNames.StoresUpdate, Description = "A store has been updated."}, -// new WebHookFilter { Name = WebHookNames.LanguagesCreate, Description = "A language has been created."}, -// new WebHookFilter { Name = WebHookNames.LanguagesUpdate, Description = "A language has been updated."}, -// new WebHookFilter { Name = WebHookNames.LanguagesDelete, Description = "A language has been deleted."}, -// new WebHookFilter { Name = WebHookNames.NewsLetterSubscriptionCreate, Description = "A news letter subscription has been created."}, -// new WebHookFilter { Name = WebHookNames.NewsLetterSubscriptionUpdate, Description = "A news letter subscription has been updated."}, -// new WebHookFilter { Name = WebHookNames.NewsLetterSubscriptionDelete, Description = "A news letter subscription has been deleted."} -// }; - -// public Task> GetFiltersAsync() -// { -// return Task.FromResult(this.filters); -// } -// } -//} diff --git a/Nop.Plugin.Api/WebHooks/NopWebHooksLogger.cs b/Nop.Plugin.Api/WebHooks/NopWebHooksLogger.cs deleted file mode 100644 index 748c436..0000000 --- a/Nop.Plugin.Api/WebHooks/NopWebHooksLogger.cs +++ /dev/null @@ -1,65 +0,0 @@ -//using Microsoft.AspNet.WebHooks.Diagnostics; -//using Nop.Core; -//using Nop.Core.Data; -//using Nop.Core.Domain.Logging; -//using Nop.Core.Infrastructure; -//using Nop.Plugin.Api.Domain; -//using System; -//using System.IO; -//using System.Web.Http.Tracing; - -//namespace Nop.Plugin.Api.WebHooks -//{ -// /// -// /// This Logger is injected into the WebHooks classes that use async calls, which are -// /// executed in different threads and at the time of execution the HttpContext as well its -// /// HttpContext.RequestServices may not be avilable. So any calls to EngineContext.Current.Resolve() will throw -// /// an exception i.e we can't use the nopCommerce ILogger service which tries to resolve the current store etc. -// /// -// public class NopWebHooksLogger : ILogger -// { -// private readonly bool _enableLogging; -// private readonly IRepository _logRepository; - -// private static object lockObject = new object(); - -// public NopWebHooksLogger(ApiSettings apiSettings, IRepository logRepository) -// { -// _enableLogging = apiSettings.EnableLogging; -// _logRepository = logRepository; -// } - -// public void Log(TraceLevel level, string message, Exception ex) -// { -// try -// { -// if (_enableLogging) -// { -// if (message != null) -// { -// lock (lockObject) -// { -// var log = new Log -// { -// LogLevel = LogLevel.Information, -// ShortMessage = message, -// FullMessage = ex?.ToString(), -// IpAddress = "", -// Customer = null, -// PageUrl = "", -// ReferrerUrl = "", -// CreatedOnUtc = DateTime.UtcNow -// }; - -// _logRepository.Insert(log); -// } -// } - -// } -// } -// catch (Exception e) -// { -// } -// } -// } -//} diff --git a/Nop.Plugin.Api/WebHooks/WebHookEventConsumer.cs b/Nop.Plugin.Api/WebHooks/WebHookEventConsumer.cs deleted file mode 100644 index f2ce8eb..0000000 --- a/Nop.Plugin.Api/WebHooks/WebHookEventConsumer.cs +++ /dev/null @@ -1,558 +0,0 @@ -//using System.Collections.Generic; -//using System.Linq; -//using Nop.Core; -//using Nop.Core.Domain.Catalog; -//using Nop.Core.Domain.Common; -//using Nop.Core.Domain.Customers; -//using Nop.Core.Domain.Localization; -//using Nop.Core.Domain.Media; -//using Nop.Core.Events; -//using Nop.Core.Infrastructure; -//using Nop.Plugin.Api.Services; -//using Nop.Services.Events; -//using Nop.Plugin.Api.DTOs.Customers; -//using Nop.Plugin.Api.Constants; -//using Nop.Plugin.Api.DTOs.Products; -//using Nop.Plugin.Api.Helpers; -//using Nop.Plugin.Api.DTOs.Categories; -//using Nop.Core.Domain.Orders; -//using Nop.Core.Domain.Stores; -//using Nop.Plugin.Api.DTOs.Languages; -//using Nop.Plugin.Api.DTOs.Orders; -//using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -//using Nop.Plugin.Api.DTOs.Stores; -//using Nop.Plugin.Api.MappingExtensions; -//using Nop.Services.Catalog; -//using Nop.Services.Stores; - -//namespace Nop.Plugin.Api.WebHooks -//{ -// using Microsoft.AspNet.WebHooks; -// using Nop.Core.Caching; -// using Nop.Core.Domain.Messages; - -// public class WebHookEventConsumer : IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer>, -// IConsumer> -// { -// private IWebHookManager _webHookManager; -// private readonly ICustomerApiService _customerApiService; -// private readonly ICategoryApiService _categoryApiService; -// private readonly IProductApiService _productApiService; -// private readonly IProductService _productService; -// private readonly ICategoryService _categoryService; -// private readonly IStoreMappingService _storeMappingService; -// private readonly IProductPictureService _productPictureService; -// private readonly IStaticCacheManager _cacheManager; - -// private IDTOHelper _dtoHelper; - -// public WebHookEventConsumer(IStoreService storeService) -// { -// _customerApiService = EngineContext.Current.Resolve(); -// _categoryApiService = EngineContext.Current.Resolve(); -// _productApiService = EngineContext.Current.Resolve(); -// _dtoHelper = EngineContext.Current.Resolve(); -// _productPictureService = EngineContext.Current.Resolve(); -// _productService = EngineContext.Current.Resolve(); -// _categoryService = EngineContext.Current.Resolve(); -// _storeMappingService = EngineContext.Current.Resolve(); -// _cacheManager = EngineContext.Current.Resolve(); -// } - -// private IWebHookManager WebHookManager -// { -// get -// { -// if (_webHookManager == null) -// { -// IWebHookService webHookService = EngineContext.Current.Resolve(); -// _webHookManager = webHookService.GetWebHookManager(); -// } - -// return _webHookManager; -// } -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// // There is no need to send webhooks for guest customers. -// if (eventMessage.Entity.IsGuest()) -// { -// return; -// } - -// CustomerDto customer = _customerApiService.GetCustomerById(eventMessage.Entity.Id); -// var storeIds = new List(); - -// if (customer.RegisteredInStoreId.HasValue) -// { -// storeIds.Add(customer.RegisteredInStoreId.Value); -// } - -// NotifyRegisteredWebHooks(customer, WebHookNames.CustomersCreate, storeIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// // There is no need to send webhooks for guest customers. -// if (eventMessage.Entity.IsGuest()) -// { -// return; -// } - -// CustomerDto customer = _customerApiService.GetCustomerById(eventMessage.Entity.Id, true); - -// // In nopCommerce the Customer, Product, Category and Order entities are not deleted. -// // Instead the Deleted property of the entity is set to true. -// string webhookEvent = WebHookNames.CustomersUpdate; - -// if (customer.Deleted == true) -// { -// webhookEvent = WebHookNames.CustomersDelete; -// } - -// var storeIds = new List(); - -// if (customer.RegisteredInStoreId.HasValue) -// { -// storeIds.Add(customer.RegisteredInStoreId.Value); -// } - -// NotifyRegisteredWebHooks(customer, webhookEvent, storeIds); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(eventMessage.Entity); - -// // The Store mappings of the product are still not saved, so all webhooks will be triggered -// // no matter for which store are registered. -// NotifyRegisteredWebHooks(productDto, WebHookNames.ProductsCreate, productDto.StoreIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(eventMessage.Entity); - -// ProductUpdated(productDto); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// CategoryDto categoryDto = _dtoHelper.PrepareCategoryDTO(eventMessage.Entity); - -// // The Store mappings of the category are still not saved, so all webhooks will be triggered -// // no matter for which store are registered. -// NotifyRegisteredWebHooks(categoryDto, WebHookNames.CategoriesCreate, categoryDto.StoreIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// CategoryDto categoryDto = _dtoHelper.PrepareCategoryDTO(eventMessage.Entity); - -// string webhookEvent = WebHookNames.CategoriesUpdate; - -// if (categoryDto.Deleted == true) -// { -// webhookEvent = WebHookNames.CategoriesDelete; -// } - -// NotifyRegisteredWebHooks(categoryDto, webhookEvent, categoryDto.StoreIds); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// OrderDto orderDto = _dtoHelper.PrepareOrderDTO(eventMessage.Entity); - -// var storeIds = new List(); - -// if (orderDto.StoreId.HasValue) -// { -// storeIds.Add(orderDto.StoreId.Value); -// } - -// NotifyRegisteredWebHooks(orderDto, WebHookNames.OrdersCreate, storeIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// OrderDto orderDto = _dtoHelper.PrepareOrderDTO(eventMessage.Entity); - -// string webhookEvent = WebHookNames.OrdersUpdate; - -// if (orderDto.Deleted == true) -// { -// webhookEvent = WebHookNames.OrdersDelete; -// } - -// var storeIds = new List(); - -// if (orderDto.StoreId.HasValue) -// { -// storeIds.Add(orderDto.StoreId.Value); -// } - -// NotifyRegisteredWebHooks(orderDto, webhookEvent, storeIds); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// HandleStoreMappingEvent(eventMessage.Entity.EntityId, eventMessage.Entity.EntityName); -// } - -// public void HandleEvent(EntityDeletedEvent eventMessage) -// { -// HandleStoreMappingEvent(eventMessage.Entity.EntityId, eventMessage.Entity.EntityName); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// if (eventMessage.Entity.Key == NopCustomerDefaults.FirstNameAttribute || -// eventMessage.Entity.Key == NopCustomerDefaults.LastNameAttribute || -// eventMessage.Entity.Key == NopCustomerDefaults.LanguageIdAttribute) -// { -// var customerDto = _customerApiService.GetCustomerById(eventMessage.Entity.EntityId); - -// var storeIds = new List(); - -// if (customerDto.RegisteredInStoreId.HasValue) -// { -// storeIds.Add(customerDto.RegisteredInStoreId.Value); -// } - -// NotifyRegisteredWebHooks(customerDto, WebHookNames.CustomersUpdate, storeIds); -// } -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// if (eventMessage.Entity.Key == NopCustomerDefaults.FirstNameAttribute || -// eventMessage.Entity.Key == NopCustomerDefaults.LastNameAttribute || -// eventMessage.Entity.Key == NopCustomerDefaults.LanguageIdAttribute) -// { -// var customerDto = _customerApiService.GetCustomerById(eventMessage.Entity.EntityId); - -// var storeIds = new List(); - -// if (customerDto.RegisteredInStoreId.HasValue) -// { -// storeIds.Add(customerDto.RegisteredInStoreId.Value); -// } - -// NotifyRegisteredWebHooks(customerDto, WebHookNames.CustomersUpdate, storeIds); -// } -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// StoreDto storeDto = _dtoHelper.PrepareStoreDTO(eventMessage.Entity); - -// int storeId; - -// if (int.TryParse(storeDto.Id, out storeId)) -// { -// var storeIds = new List(); -// storeIds.Add(storeId); - -// NotifyRegisteredWebHooks(storeDto, WebHookNames.StoresUpdate, storeIds); -// } -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// NotifyProductCategoryMappingWebhook(eventMessage.Entity, WebHookNames.ProductCategoryMapsCreate); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// NotifyProductCategoryMappingWebhook(eventMessage.Entity, WebHookNames.ProductCategoryMapsUpdate); -// } - -// public void HandleEvent(EntityDeletedEvent eventMessage) -// { -// NotifyProductCategoryMappingWebhook(eventMessage.Entity, WebHookNames.ProductCategoryMapsDelete); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// LanguageDto langaDto = _dtoHelper.PrepateLanguageDto(eventMessage.Entity); - -// NotifyRegisteredWebHooks(langaDto, WebHookNames.LanguagesCreate, langaDto.StoreIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// LanguageDto langaDto = _dtoHelper.PrepateLanguageDto(eventMessage.Entity); - -// NotifyRegisteredWebHooks(langaDto, WebHookNames.LanguagesUpdate, langaDto.StoreIds); -// } - -// public void HandleEvent(EntityDeletedEvent eventMessage) -// { -// LanguageDto langaDto = _dtoHelper.PrepateLanguageDto(eventMessage.Entity); - -// NotifyRegisteredWebHooks(langaDto, WebHookNames.LanguagesDelete, langaDto.StoreIds); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// var product = _productApiService.GetProductById(eventMessage.Entity.ProductId); - -// if (product != null) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(product); - -// ProductUpdated(productDto); -// } -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// var product = _productApiService.GetProductById(eventMessage.Entity.ProductId); - -// if (product != null) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(product); - -// ProductUpdated(productDto); -// } -// } - -// public void HandleEvent(EntityDeletedEvent eventMessage) -// { -// var product = _productApiService.GetProductById(eventMessage.Entity.ProductId); - -// if (product != null) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(product); - -// ProductUpdated(productDto); -// } -// } - -// // We trigger a product updated WebHook when a picture used in a product is updated. -// // This is required, because when the product title is changed, the product is updated first -// // and then the picture urls are chaged. In order for the WebHook consumer to have the latest -// // product picture urls the following code is used. -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// var productPicture = _productPictureService.GetProductPictureByPictureId(eventMessage.Entity.Id); - -// if (productPicture != null) -// { -// var product = _productApiService.GetProductById(productPicture.ProductId); - -// if (product != null) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(product); - -// ProductUpdated(productDto); -// } -// } -// } - -// public void HandleEvent(EntityDeletedEvent eventMessage) -// { -// _cacheManager.RemoveByPattern(Configurations.NEWSLETTER_SUBSCRIBERS_KEY); - -// NewsLetterSubscriptionDto newsLetterSubscriptionDto = eventMessage.Entity.ToDto(); - -// var storeIds = new List -// { -// newsLetterSubscriptionDto.StoreId -// }; - -// NotifyRegisteredWebHooks(newsLetterSubscriptionDto, WebHookNames.NewsLetterSubscriptionDelete, storeIds); -// } - -// public void HandleEvent(EntityInsertedEvent eventMessage) -// { -// _cacheManager.RemoveByPattern(Configurations.NEWSLETTER_SUBSCRIBERS_KEY); - -// NewsLetterSubscriptionDto newsLetterSubscriptionDto = eventMessage.Entity.ToDto(); - -// var storeIds = new List -// { -// newsLetterSubscriptionDto.StoreId -// }; - -// NotifyRegisteredWebHooks(newsLetterSubscriptionDto, WebHookNames.NewsLetterSubscriptionCreate, storeIds); -// } - -// public void HandleEvent(EntityUpdatedEvent eventMessage) -// { -// _cacheManager.RemoveByPattern(Configurations.NEWSLETTER_SUBSCRIBERS_KEY); - -// NewsLetterSubscriptionDto newsLetterSubscriptionDto = eventMessage.Entity.ToDto(); - -// var storeIds = new List -// { -// newsLetterSubscriptionDto.StoreId -// }; - -// NotifyRegisteredWebHooks(newsLetterSubscriptionDto, WebHookNames.NewsLetterSubscriptionUpdate, storeIds); -// } - -// private void NotifyProductCategoryMappingWebhook(ProductCategory productCategory, string eventName) -// { -// var storeIds = GetStoreIdsForProductCategoryMap(productCategory); - -// if (storeIds == null) -// { -// return; -// } - -// ProductCategoryMappingDto productCategoryMappingDto = productCategory.ToDto(); - -// NotifyRegisteredWebHooks(productCategoryMappingDto, eventName, storeIds); -// } - -// private List GetStoreIdsForProductCategoryMap(ProductCategory productCategory) -// { -// // Send a webhook event only for the stores that can access the product and category -// // in the current product category map. -// Product product = _productService.GetProductById(productCategory.ProductId); -// Category category = _categoryService.GetCategoryById(productCategory.CategoryId); - -// if (product == null || category == null) -// { -// return null; -// } - -// var productStoreIds = _storeMappingService.GetStoresIdsWithAccess(product); - -// var categoryStoreIds = _storeMappingService.GetStoresIdsWithAccess(category); - -// return productStoreIds.Intersect(categoryStoreIds).ToList(); -// } - -// private void ProductUpdated(ProductDto productDto) -// { -// string webhookEvent = WebHookNames.ProductsUpdate; - -// if (productDto.Deleted == true) -// { -// webhookEvent = WebHookNames.ProductsDelete; -// } - -// NotifyRegisteredWebHooks(productDto, webhookEvent, productDto.StoreIds); -// } - -// private void HandleStoreMappingEvent(int entityId, string entityName) -// { -// // When creating or editing a category after saving the store mapping the category is not updated -// // so we should listen for StoreMapping update/delete and fire a webhook with the updated entityDto(with correct storeIds). -// if (entityName == "Category") -// { -// var category = _categoryApiService.GetCategoryById(entityId); - -// if (category != null) -// { -// CategoryDto categoryDto = _dtoHelper.PrepareCategoryDTO(category); - -// string webhookEvent = WebHookNames.CategoriesUpdate; - -// if (categoryDto.Deleted == true) -// { -// webhookEvent = WebHookNames.CategoriesDelete; -// } - -// NotifyRegisteredWebHooks(categoryDto, webhookEvent, categoryDto.StoreIds); -// } -// } -// else if (entityName == "Product") -// { -// var product = _productApiService.GetProductById(entityId); - -// if (product != null) -// { -// ProductDto productDto = _dtoHelper.PrepareProductDTO(product); - -// string webhookEvent = WebHookNames.ProductsUpdate; - -// if (productDto.Deleted == true) -// { -// webhookEvent = WebHookNames.ProductsDelete; -// } - -// NotifyRegisteredWebHooks(productDto, webhookEvent, productDto.StoreIds); -// } -// } -// } - -// private void NotifyRegisteredWebHooks(T entityDto, string webhookEvent, List storeIds) -// { -// if (storeIds.Count > 0) -// { -// // Notify all webhooks that the entity is mapped to their store. -// WebHookManager.NotifyAllAsync(webhookEvent, new { Item = entityDto }, (hook, hookUser) => IsEntityMatchingTheWebHookStoreId(hookUser, storeIds)); - -// if (typeof(T) == typeof(ProductDto) || typeof(T) == typeof(CategoryDto)) -// { -// NotifyUnmappedEntityWebhooks(entityDto, storeIds); -// } -// } -// else -// { -// WebHookManager.NotifyAllAsync(webhookEvent, new { Item = entityDto }); -// } -// } - -// private void NotifyUnmappedEntityWebhooks(T entityDto, List storeIds) -// { -// if (typeof(T) == typeof(ProductDto)) -// { -// // The product is not mapped to the store. -// // Notify all webhooks that the entity is not mapped to their store. -// WebHookManager.NotifyAllAsync(WebHookNames.ProductsUnmap, new { Item = entityDto }, -// (hook, hookUser) => !IsEntityMatchingTheWebHookStoreId(hookUser, storeIds)); -// } -// else if (typeof(T) == typeof(CategoryDto)) -// { -// // The category is not mapped to the store. -// // Notify all webhooks that the entity is not mapped to their store. -// WebHookManager.NotifyAllAsync(WebHookNames.CategoriesUnmap, new { Item = entityDto }, -// (hook, hookUser) => !IsEntityMatchingTheWebHookStoreId(hookUser, storeIds)); -// } -// } - -// private bool IsEntityMatchingTheWebHookStoreId(string webHookUser, List storeIds) -// { -// // When we register the webhooks we add "-storeId" at the end of the webHookUser string. -// // That way we can check to which store is mapped the webHook. -// foreach (var id in storeIds) -// { -// if (webHookUser.EndsWith("-" + id)) -// { -// return true; -// } -// } - -// return false; -// } -// } -//} diff --git a/Nop.Plugin.Api/upgrade_script.sql b/Nop.Plugin.Api/upgrade_script.sql deleted file mode 100644 index 0643f57..0000000 --- a/Nop.Plugin.Api/upgrade_script.sql +++ /dev/null @@ -1,74 +0,0 @@ --- Used to migrate the clients tables used prior to 4.0 into the tables used by the Identity Server -- - -BEGIN TRANSACTION; - - -- Clients -- - Insert into Clients - Select 2592000 as AbsoluteRefreshTokenLifetime, - 3600 as AccessTokenLifetime, - 0 as AccessTokenType, - 0 as AllowAccessTokensViaBrowser, - 1 as AllowOfflineAccess, - 0 as AllowPlainTextPkce, - 1 as AllowRememberConsent, - 0 as AlwaysIncludeUserClaimsInIdToken, - 0 as AlwaysSendClientClaims, - 300 as AuthorizationCodeLifetime, - [ClientId] as ClientId, - [Name] as ClientName, - NULL as ClientUri, - 1 as EnableLocalLogin, - [IsActive] as [Enabled], - 300 as IdentityTokenLifetime, - 0 as IncludeJwtId, - NULL as LogoUri, - 'oidc' as ProtocolType, - 1 as RefreshTokenExpiration, - 1 as RefreshTokenUsage, - 1 as RequireClientSecret, - 1 as RequireConsent, - 0 as RequirePkce, - 1296000 as SlidingRefreshTokenLifetime, - 0 as UpdateAccessTokenClaimsOnRefresh, - 1 as BackChannelLogoutSessionRequired, - NULL as BackChannelLogoutUri, - 'client_' as ClientClaimsPrefix, - NULL as ConsentLifetime, - NULL as [Description], - 1 as FrontChannelLogoutSessionRequired, - NULL as FrontChannelLogoutUri, - NULL as PairWiseSubjectSalt from API_Clients - - -- ClientClaims -- - Insert into ClientClaims - Select Id as ClientId, 'sub' as [Type], ClientId as [Value] from Clients - - Insert into ClientClaims - Select Id as ClientId, 'name' as [Type], [ClientName] as [Value] from Clients - - -- ClientGrantTypes -- - Insert into ClientGrantTypes - Select Id as ClientId, 'authorization_code' as GrantType from Clients - - Insert into ClientGrantTypes - Select Id as ClientId, 'refresh_token' as GrantType from Clients - - Insert into ClientGrantTypes - Select Id as ClientId, 'urn:ietf:params:oauth:grant-type:jwt-bearer' as GrantType from Clients - - -- ClientRedirectUris -- - Insert into ClientRedirectUris - Select Client_id as ClientId, CallbackUrl as RedirectUri from (Select Clients.Id as Client_id, Clients.ClientId, CallbackUrl from Clients - inner join API_Clients on Clients.ClientId = API_Clients.ClientId) as JoinedClients - -- ClientScopes -- - Insert into ClientScopes - Select Id as ClientId, 'nop_api' as Scope from Clients - - -- ClientSecrets -- - Insert into ClientSecrets - Select Client_id as ClientId, ClientSecret as [Description], NULL as Expiration, 'SharedSecret' as [Type], ClientSecret as [Value] - from (Select Clients.Id as Client_id, Clients.ClientId, ClientSecret from Clients - inner join API_Clients on Clients.ClientId = API_Clients.ClientId) as JoinedClients - - drop table API_Clients; -COMMIT; \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/CategoryApiService.cs b/Services/CategoryApiService.cs similarity index 95% rename from Nop.Plugin.Api/Services/CategoryApiService.cs rename to Services/CategoryApiService.cs index db2ec85..82c472a 100644 --- a/Nop.Plugin.Api/Services/CategoryApiService.cs +++ b/Services/CategoryApiService.cs @@ -1,119 +1,119 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Services -{ - public class CategoryApiService : ICategoryApiService - { - private readonly IStoreMappingService _storeMappingService; - private readonly IRepository _categoryRepository; - private readonly IRepository _productCategoryMappingRepository; - - public CategoryApiService(IRepository categoryRepository, - IRepository productCategoryMappingRepository, - IStoreMappingService storeMappingService) - { - _categoryRepository = categoryRepository; - _productCategoryMappingRepository = productCategoryMappingRepository; - _storeMappingService = storeMappingService; - } - - public IList GetCategories(IList ids = null, - DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, - int? productId = null, - bool? publishedStatus = null) - { - var query = GetCategoriesQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, publishedStatus, productId, ids); - - - if (sinceId > 0) - { - query = query.Where(c => c.Id > sinceId); - } - - return new ApiList(query, page - 1, limit); - } - - public Category GetCategoryById(int id) - { - if (id <= 0) - return null; - - var category = _categoryRepository.Table.FirstOrDefault(cat => cat.Id == id && !cat.Deleted); - - return category; - } - - public int GetCategoriesCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, - DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, - bool? publishedStatus = null, int? productId = null) - { - var query = GetCategoriesQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, - publishedStatus, productId); - - return query.Count(c => _storeMappingService.Authorize(c)); - } - - private IQueryable GetCategoriesQuery( - DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, - bool? publishedStatus = null, int? productId = null, IList ids = null) - { - var query = _categoryRepository.Table; - - if (ids != null && ids.Count > 0) - { - query = query.Where(c => ids.Contains(c.Id)); - } - - if (publishedStatus != null) - { - query = query.Where(c => c.Published == publishedStatus.Value); - } - - query = query.Where(c => !c.Deleted); - - if (createdAtMin != null) - { - query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); - } - - if (createdAtMax != null) - { - - query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); - } - - if (updatedAtMin != null) - { - query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); - } - - if (updatedAtMax != null) - { - query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); - } - - if (productId != null) - { - var categoryMappingsForProduct = from productCategoryMapping in _productCategoryMappingRepository.Table - where productCategoryMapping.ProductId == productId - select productCategoryMapping; - - query = from category in query - join productCategoryMapping in categoryMappingsForProduct on category.Id equals productCategoryMapping.CategoryId - select category; - } - - query = query.OrderBy(category => category.Id); - - return query; - } - } +using Nop.Core.Domain.Catalog; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class CategoryApiService : ICategoryApiService + { + private readonly IStoreMappingService _storeMappingService; + private readonly IRepository _categoryRepository; + private readonly IRepository _productCategoryMappingRepository; + + public CategoryApiService(IRepository categoryRepository, + IRepository productCategoryMappingRepository, + IStoreMappingService storeMappingService) + { + _categoryRepository = categoryRepository; + _productCategoryMappingRepository = productCategoryMappingRepository; + _storeMappingService = storeMappingService; + } + + public IList GetCategories(IList ids = null, + DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, + int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, + int? productId = null, + bool? publishedStatus = null) + { + var query = GetCategoriesQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, publishedStatus, productId, ids); + + + if (sinceId > 0) + { + query = query.Where(c => c.Id > sinceId); + } + + return new ApiList(query, page - 1, limit); + } + + public Category GetCategoryById(int id) + { + if (id <= 0) + return null; + + var category = _categoryRepository.Table.FirstOrDefault(cat => cat.Id == id && !cat.Deleted); + + return category; + } + + public int GetCategoriesCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, + DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, + bool? publishedStatus = null, int? productId = null) + { + var query = GetCategoriesQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, + publishedStatus, productId); + + return query.Count(c => _storeMappingService.Authorize(c)); + } + + private IQueryable GetCategoriesQuery( + DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, + bool? publishedStatus = null, int? productId = null, IList ids = null) + { + var query = _categoryRepository.Table; + + if (ids != null && ids.Count > 0) + { + query = query.Where(c => ids.Contains(c.Id)); + } + + if (publishedStatus != null) + { + query = query.Where(c => c.Published == publishedStatus.Value); + } + + query = query.Where(c => !c.Deleted); + + if (createdAtMin != null) + { + query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); + } + + if (createdAtMax != null) + { + + query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); + } + + if (updatedAtMin != null) + { + query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); + } + + if (updatedAtMax != null) + { + query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); + } + + if (productId != null) + { + var categoryMappingsForProduct = from productCategoryMapping in _productCategoryMappingRepository.Table + where productCategoryMapping.ProductId == productId + select productCategoryMapping; + + query = from category in query + join productCategoryMapping in categoryMappingsForProduct on category.Id equals productCategoryMapping.CategoryId + select category; + } + + query = query.OrderBy(category => category.Id); + + return query; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/CustomerApiService.cs b/Services/CustomerApiService.cs similarity index 55% rename from Nop.Plugin.Api/Services/CustomerApiService.cs rename to Services/CustomerApiService.cs index d5fe55d..a05de65 100644 --- a/Nop.Plugin.Api/Services/CustomerApiService.cs +++ b/Services/CustomerApiService.cs @@ -1,523 +1,535 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Nop.Core.Data; -using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.DTOs.Customers; -using System.Linq; -using System.Linq.Dynamic.Core; -using System.Text.RegularExpressions; -using Nop.Core; -using Nop.Core.Domain.Common; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; -using Nop.Plugin.Api.Helpers; -using Nop.Plugin.Api.MappingExtensions; -using Nop.Services.Localization; -using Nop.Services.Stores; -using Nop.Core.Domain.Messages; -using Nop.Core.Caching; - -namespace Nop.Plugin.Api.Services -{ - public class CustomerApiService : ICustomerApiService - { - private const string FirstName = "firstname"; - private const string LastName = "lastname"; - private const string LanguageId = "languageid"; - private const string DateOfBirth = "dateofbirth"; - private const string Gender = "gender"; - private const string KeyGroup = "customer"; - - private readonly IStoreContext _storeContext; - private readonly ILanguageService _languageService; - private readonly IStoreMappingService _storeMappingService; - private readonly IRepository _customerRepository; - private readonly IRepository _genericAttributeRepository; - private readonly IRepository _subscriptionRepository; - private readonly IStaticCacheManager _cacheManager; - - public CustomerApiService(IRepository customerRepository, - IRepository genericAttributeRepository, - IRepository subscriptionRepository, - IStoreContext storeContext, - ILanguageService languageService, - IStoreMappingService storeMappingService, - IStaticCacheManager staticCacheManager) - { - _customerRepository = customerRepository; - _genericAttributeRepository = genericAttributeRepository; - _subscriptionRepository = subscriptionRepository; - _storeContext = storeContext; - _languageService = languageService; - _storeMappingService = storeMappingService; - _cacheManager = staticCacheManager; - } - - public IList GetCustomersDtos(DateTime? createdAtMin = null, DateTime? createdAtMax = null, int limit = Configurations.DefaultLimit, - int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId) - { - var query = GetCustomersQuery(createdAtMin, createdAtMax, sinceId); - - var result = HandleCustomerGenericAttributes(null, query, limit, page); - - SetNewsletterSubscribtionStatus(result); - - return result; - } - - public int GetCustomersCount() - { - return _customerRepository.Table.Count(customer => !customer.Deleted - && (customer.RegisteredInStoreId == 0 || customer.RegisteredInStoreId == _storeContext.CurrentStore.Id)); - } - - // Need to work with dto object so we can map the first and last name from generic attributes table. - public IList Search(string queryParams = "", string order = Configurations.DefaultOrder, - int page = Configurations.DefaultPageValue, int limit = Configurations.DefaultLimit) - { - IList result = new List(); - - var searchParams = EnsureSearchQueryIsValid(queryParams, ParseSearchQuery); - - if (searchParams != null) - { - var query = _customerRepository.Table.Where(customer => !customer.Deleted); - - foreach (var searchParam in searchParams) - { - // Skip non existing properties. - if (ReflectionHelper.HasProperty(searchParam.Key, typeof(Customer))) - { - - // @0 is a placeholder used by dynamic linq and it is used to prevent possible sql injections. - query = query.Where(string.Format("{0} = @0 || {0}.Contains(@0)", searchParam.Key), searchParam.Value); - } - // The code bellow will search in customer addresses as well. - //else if (HasProperty(searchParam.Key, typeof(Address))) - //{ - // query = query.Where(string.Format("Addresses.Where({0} == @0).Any()", searchParam.Key), searchParam.Value); - //} - } - - result = HandleCustomerGenericAttributes(searchParams, query, limit, page, order); - } - - return result; - } - - public Dictionary GetFirstAndLastNameByCustomerId(int customerId) - { - return _genericAttributeRepository.Table.Where( - x => - x.KeyGroup == KeyGroup && x.EntityId == customerId && - (x.Key == FirstName || x.Key == LastName)).ToDictionary(x => x.Key.ToLowerInvariant(), y => y.Value); - } - - public Customer GetCustomerEntityById(int id) - { - var customer = _customerRepository.Table.FirstOrDefault(c => c.Id == id && !c.Deleted); - - return customer; - } - - public CustomerDto GetCustomerById(int id, bool showDeleted = false) - { - if (id == 0) - return null; - - // Here we expect to get two records, one for the first name and one for the last name. - var customerAttributeMappings = (from customer in _customerRepository.Table //NoTracking - join attribute in _genericAttributeRepository.Table//NoTracking - on customer.Id equals attribute.EntityId - where customer.Id == id && - attribute.KeyGroup == "Customer" - select new CustomerAttributeMappingDto - { - Attribute = attribute, - Customer = customer - }).ToList(); - - CustomerDto customerDto = null; - - // This is in case we have first and last names set for the customer. - if (customerAttributeMappings.Count > 0) - { - var customer = customerAttributeMappings.First().Customer; - // The customer object is the same in all mappings. - customerDto = customer.ToDto(); - - var defaultStoreLanguageId = GetDefaultStoreLangaugeId(); - - // If there is no Language Id generic attribute create one with the default language id. - if (!customerAttributeMappings.Any(cam => cam?.Attribute != null && cam.Attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase))) - { - var languageId = new GenericAttribute - { - Key = LanguageId, - Value = defaultStoreLanguageId.ToString() - }; - - var customerAttributeMappingDto = new CustomerAttributeMappingDto - { - Customer = customer, - Attribute = languageId - }; - - customerAttributeMappings.Add(customerAttributeMappingDto); - } - - foreach (var mapping in customerAttributeMappings) - { - if (!showDeleted && mapping.Customer.Deleted) - { - continue; - } - - if (mapping.Attribute != null) - { - if (mapping.Attribute.Key.Equals(FirstName, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.FirstName = mapping.Attribute.Value; - } - else if (mapping.Attribute.Key.Equals(LastName, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.LastName = mapping.Attribute.Value; - } - else if (mapping.Attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.LanguageId = mapping.Attribute.Value; - } - else if (mapping.Attribute.Key.Equals(DateOfBirth, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.DateOfBirth = string.IsNullOrEmpty(mapping.Attribute.Value) ? (DateTime?)null : DateTime.Parse(mapping.Attribute.Value); - } - else if (mapping.Attribute.Key.Equals(Gender, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.Gender = mapping.Attribute.Value; - } - } - } - } - else - { - // This is when we do not have first and last name set. - var currentCustomer = _customerRepository.Table.FirstOrDefault(customer => customer.Id == id); - - if (currentCustomer != null) - { - if (showDeleted || !currentCustomer.Deleted) - { - customerDto = currentCustomer.ToDto(); - } - } - } - - SetNewsletterSubscribtionStatus(customerDto); - - return customerDto; - } - - private Dictionary EnsureSearchQueryIsValid(string query, Func> parseSearchQuery) - { - if (!string.IsNullOrEmpty(query)) - { - return parseSearchQuery(query); - } - - return null; - } - - private Dictionary ParseSearchQuery(string query) - { - var parsedQuery = new Dictionary(); - - var splitPattern = @"(\w+):"; - - var fieldValueList = Regex.Split(query, splitPattern).Where(s => s != String.Empty).ToList(); - - if (fieldValueList.Count < 2) - { - return parsedQuery; - } - - for (var i = 0; i < fieldValueList.Count; i += 2) - { - var field = fieldValueList[i]; - var value = fieldValueList[i + 1]; - - if (!string.IsNullOrEmpty(field) && !string.IsNullOrEmpty(value)) - { - field = field.Replace("_", string.Empty); - parsedQuery.Add(field.Trim(), value.Trim()); - } - } - - return parsedQuery; - } - - /// - /// The idea of this method is to get the first and last name from the GenericAttribute table and to set them in the CustomerDto object. - /// - /// Search parameters is used to shrinc the range of results from the GenericAttibutes table - /// to be only those with specific search parameter (i.e. currently we focus only on first and last name). - /// Query parameter represents the current customer records which we will join with GenericAttributes table. - /// - /// - /// - /// - private IList HandleCustomerGenericAttributes(IReadOnlyDictionary searchParams, IQueryable query, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, string order = Configurations.DefaultOrder) - { - // Here we join the GenericAttribute records with the customers and making sure that we are working only with the attributes - // that are in the customers keyGroup and their keys are either first or last name. - // We are returning a collection with customer record and attribute record. - // It will look something like: - // customer data for customer 1 - // attribute that contains the first name of customer 1 - // attribute that contains the last name of customer 1 - // customer data for customer 2, - // attribute that contains the first name of customer 2 - // attribute that contains the last name of customer 2 - // etc. - - var allRecordsGroupedByCustomerId = - (from customer in query - from attribute in _genericAttributeRepository.Table - .Where(attr => attr.EntityId == customer.Id && - attr.KeyGroup == "Customer").DefaultIfEmpty() - select new CustomerAttributeMappingDto - { - Attribute = attribute, - Customer = customer - }).GroupBy(x => x.Customer.Id); - - if (searchParams != null && searchParams.Count > 0) - { - if (searchParams.ContainsKey(FirstName)) - { - allRecordsGroupedByCustomerId = GetCustomerAttributesMappingsByKey(allRecordsGroupedByCustomerId, FirstName, searchParams[FirstName]); - } - - if (searchParams.ContainsKey(LastName)) - { - allRecordsGroupedByCustomerId = GetCustomerAttributesMappingsByKey(allRecordsGroupedByCustomerId, LastName, searchParams[LastName]); - } - - if (searchParams.ContainsKey(LanguageId)) - { - allRecordsGroupedByCustomerId = GetCustomerAttributesMappingsByKey(allRecordsGroupedByCustomerId, LanguageId, searchParams[LanguageId]); - } - - if (searchParams.ContainsKey(DateOfBirth)) - { - allRecordsGroupedByCustomerId = GetCustomerAttributesMappingsByKey(allRecordsGroupedByCustomerId, DateOfBirth, searchParams[DateOfBirth]); - } - - if (searchParams.ContainsKey(Gender)) - { - allRecordsGroupedByCustomerId = GetCustomerAttributesMappingsByKey(allRecordsGroupedByCustomerId, Gender, searchParams[Gender]); - } - } - - var result = GetFullCustomerDtos(allRecordsGroupedByCustomerId, page, limit, order); - - return result; - } - - /// - /// This method is responsible for getting customer dto records with first and last names set from the attribute mappings. - /// - private IList GetFullCustomerDtos(IQueryable> customerAttributesMappings, - int page = Configurations.DefaultPageValue, int limit = Configurations.DefaultLimit, string order = Configurations.DefaultOrder) - { - var customerDtos = new List(); - - customerAttributesMappings = customerAttributesMappings.OrderBy(x => x.Key); - - IList> customerAttributeGroupsList = new ApiList>(customerAttributesMappings, page - 1, limit); - - // Get the default language id for the current store. - var defaultLanguageId = GetDefaultStoreLangaugeId(); - - foreach (var group in customerAttributeGroupsList) - { - IList mappingsForMerge = group.Select(x => x).ToList(); - - var customerDto = Merge(mappingsForMerge, defaultLanguageId); - - customerDtos.Add(customerDto); - } - - // Needed so we can apply the order parameter - return customerDtos.AsQueryable().OrderBy(order).ToList(); - } - - private static CustomerDto Merge(IList mappingsForMerge, int defaultLanguageId) - { - // We expect the customer to be always set. - var customerDto = mappingsForMerge.First().Customer.ToDto(); - - var attributes = mappingsForMerge.Select(x => x.Attribute).ToList(); - - // If there is no Language Id generic attribute create one with the default language id. - if (!attributes.Any(atr => atr != null && atr.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase))) - { - var languageId = new GenericAttribute - { - Key = LanguageId, - Value = defaultLanguageId.ToString() - }; - - attributes.Add(languageId); - } - - foreach (var attribute in attributes) - { - if (attribute != null) - { - if (attribute.Key.Equals(FirstName, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.FirstName = attribute.Value; - } - else if (attribute.Key.Equals(LastName, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.LastName = attribute.Value; - } - else if (attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.LanguageId = attribute.Value; - } - else if (attribute.Key.Equals(DateOfBirth, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.DateOfBirth = string.IsNullOrEmpty(attribute.Value) ? (DateTime?)null : DateTime.Parse(attribute.Value); - } - else if (attribute.Key.Equals(Gender, StringComparison.InvariantCultureIgnoreCase)) - { - customerDto.Gender = attribute.Value; - } - } - } - - return customerDto; - } - - private IQueryable> GetCustomerAttributesMappingsByKey( - IQueryable> customerAttributesGroups, string key, string value) - { - // Here we filter the customerAttributesGroups to be only the ones that have the passed key parameter as a key. - var customerAttributesMappingByKey = from @group in customerAttributesGroups - where @group.Select(x => x.Attribute) - .Any(x => x.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase) && - x.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)) - select @group; - - return customerAttributesMappingByKey; - } - - private IQueryable GetCustomersQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, int sinceId = 0) - { - var query = _customerRepository.Table //NoTracking - .Where(customer => !customer.Deleted && !customer.IsSystemAccount && customer.Active); - - query = query.Where(customer => !customer.CustomerCustomerRoleMappings.Any(ccrm => ccrm.CustomerRole.Active && ccrm.CustomerRole.SystemName == NopCustomerDefaults.GuestsRoleName) - && (customer.RegisteredInStoreId == 0 || customer.RegisteredInStoreId == _storeContext.CurrentStore.Id)); - - if (createdAtMin != null) - { - query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); - } - - if (createdAtMax != null) - { - query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); - } - - query = query.OrderBy(customer => customer.Id); - - if (sinceId > 0) - { - query = query.Where(customer => customer.Id > sinceId); - } - - return query; - } - - private int GetDefaultStoreLangaugeId() - { - // Get the default language id for the current store. - var defaultLanguageId = _storeContext.CurrentStore.DefaultLanguageId; - - if (defaultLanguageId == 0) - { - var allLanguages = _languageService.GetAllLanguages(); - - var storeLanguages = allLanguages.Where(l => - _storeMappingService.Authorize(l, _storeContext.CurrentStore.Id)).ToList(); - - // If there is no language mapped to the current store, get all of the languages, - // and use the one with the first display order. This is a default nopCommerce workflow. - if (storeLanguages.Count == 0) - { - storeLanguages = allLanguages.ToList(); - } - - var defaultLanguage = storeLanguages.OrderBy(l => l.DisplayOrder).First(); - - defaultLanguageId = defaultLanguage.Id; - } - - return defaultLanguageId; - } - - [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] - private void SetNewsletterSubscribtionStatus(IList customerDtos) - { - if (customerDtos == null) - { - return; - } - - var allNewsletterCustomerEmail = GetAllNewsletterCustomersEmails(); - - foreach (var customerDto in customerDtos) - { - SetNewsletterSubscribtionStatus(customerDto, allNewsletterCustomerEmail); - } - } - - private void SetNewsletterSubscribtionStatus(BaseCustomerDto customerDto, IEnumerable allNewsletterCustomerEmail = null) - { - if (customerDto == null || String.IsNullOrEmpty(customerDto.Email)) - { - return; - } - - if (allNewsletterCustomerEmail == null) - { - allNewsletterCustomerEmail = GetAllNewsletterCustomersEmails(); - } - - if (allNewsletterCustomerEmail != null && allNewsletterCustomerEmail.Contains(customerDto.Email.ToLowerInvariant())) - { - customerDto.SubscribedToNewsletter = true; - } - } - - private IEnumerable GetAllNewsletterCustomersEmails() - { - return _cacheManager.Get(Configurations.NEWSLETTER_SUBSCRIBERS_KEY, () => - { - IEnumerable subscriberEmails = (from nls in _subscriptionRepository.Table - where nls.StoreId == _storeContext.CurrentStore.Id - && nls.Active - select nls.Email).ToList(); - - - subscriberEmails = subscriberEmails.Where(e => !String.IsNullOrEmpty(e)).Select(e => e.ToLowerInvariant()); - - return subscriberEmails.Where(e => !String.IsNullOrEmpty(e)).Select(e => e.ToLowerInvariant()); - }); - } - } -} \ No newline at end of file +using LinqToDB; +using Nop.Core; +using Nop.Core.Caching; +using Nop.Core.Domain.Common; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Messages; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.Helpers; +using Nop.Plugin.Api.MappingExtensions; +using Nop.Services.Customers; +using Nop.Services.Localization; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Text.RegularExpressions; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class CustomerApiService : ICustomerApiService + { + private const string FirstName = "firstname"; + private const string LastName = "lastname"; + private const string LanguageId = "languageid"; + private const string DateOfBirth = "dateofbirth"; + private const string Gender = "gender"; + private const string KeyGroup = "customer"; + + private readonly IStoreContext _storeContext; + private readonly ILanguageService _languageService; + private readonly ICustomerService _customerService; + private readonly IStoreMappingService _storeMappingService; + private readonly IRepository _customerRepository; + private readonly IRepository _customerCustomerRoleMappingRepository; + private readonly IRepository _customerRoleRepository; + private readonly IRepository _genericAttributeRepository; + private readonly IRepository _subscriptionRepository; + private readonly IStaticCacheManager _cacheManager; + + public CustomerApiService(IRepository customerRepository, + IRepository genericAttributeRepository, + IRepository subscriptionRepository, + IRepository customerCustomerRoleMappingRepository, + IRepository customerRoleRepository, + IStoreContext storeContext, + ILanguageService languageService, + IStoreMappingService storeMappingService, + IStaticCacheManager staticCacheManager, + ICustomerService customerService) + { + _customerRepository = customerRepository; + _genericAttributeRepository = genericAttributeRepository; + _subscriptionRepository = subscriptionRepository; + _customerCustomerRoleMappingRepository = customerCustomerRoleMappingRepository; + _customerRoleRepository = customerRoleRepository; + _storeContext = storeContext; + _languageService = languageService; + _storeMappingService = storeMappingService; + _cacheManager = staticCacheManager; + _customerService = customerService; + } + + public virtual IQueryable GetAllCustomers(DateTime? createdFromUtc = null, DateTime? createdToUtc = null, + int affiliateId = 0, int vendorId = 0, int[] customerRoleIds = null, + string email = null, string username = null, string firstName = null, string lastName = null, + int dayOfBirth = 0, int monthOfBirth = 0, + string company = null, string phone = null, string zipPostalCode = null, string ipAddress = null, + int pageIndex = 0, int pageSize = int.MaxValue, + int sinceId = 0, + bool getOnlyTotalCount = false) + { + var query = _customerRepository.Table; + + + if (createdFromUtc.HasValue) + query = query.Where(c => createdFromUtc.Value <= c.CreatedOnUtc); + if (createdToUtc.HasValue) + query = query.Where(c => createdToUtc.Value >= c.CreatedOnUtc); + if (affiliateId > 0) + query = query.Where(c => affiliateId == c.AffiliateId); + if (vendorId > 0) + query = query.Where(c => vendorId == c.VendorId); + if (sinceId > 0) + query = query.Where(c => c.Id > sinceId); + + query = query.Where(c => !c.Deleted); + + if (customerRoleIds != null && customerRoleIds.Length > 0) + { + query = query.Join(_customerCustomerRoleMappingRepository.Table, x => x.Id, y => y.CustomerId, + (x, y) => new { Customer = x, Mapping = y }) + .Where(z => customerRoleIds.Contains(z.Mapping.CustomerRoleId)) + .Select(z => z.Customer) + .Distinct(); + } + + if (!string.IsNullOrWhiteSpace(email)) + query = query.Where(c => c.Email.Contains(email)); + if (!string.IsNullOrWhiteSpace(username)) + query = query.Where(c => c.Username.Contains(username)); + if (!string.IsNullOrWhiteSpace(firstName)) + { + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.FirstNameAttribute && + z.Attribute.Value.Contains(firstName)) + .Select(z => z.Customer); + } + + if (!string.IsNullOrWhiteSpace(lastName)) + { + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.LastNameAttribute && + z.Attribute.Value.Contains(lastName)) + .Select(z => z.Customer); + } + + //date of birth is stored as a string into database. + //we also know that date of birth is stored in the following format YYYY-MM-DD (for example, 1983-02-18). + //so let's search it as a string + if (dayOfBirth > 0 && monthOfBirth > 0) + { + //both are specified + var dateOfBirthStr = monthOfBirth.ToString("00", CultureInfo.InvariantCulture) + "-" + dayOfBirth.ToString("00", CultureInfo.InvariantCulture); + + //z.Attribute.Value.Length - dateOfBirthStr.Length = 5 + //dateOfBirthStr.Length = 5 + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.DateOfBirthAttribute && + z.Attribute.Value.Substring(5, 5) == dateOfBirthStr) + .Select(z => z.Customer); + } + else if (dayOfBirth > 0) + { + //only day is specified + var dateOfBirthStr = dayOfBirth.ToString("00", CultureInfo.InvariantCulture); + + //z.Attribute.Value.Length - dateOfBirthStr.Length = 8 + //dateOfBirthStr.Length = 2 + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.DateOfBirthAttribute && + z.Attribute.Value.Substring(8, 2) == dateOfBirthStr) + .Select(z => z.Customer); + } + else if (monthOfBirth > 0) + { + //only month is specified + var dateOfBirthStr = "-" + monthOfBirth.ToString("00", CultureInfo.InvariantCulture) + "-"; + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.DateOfBirthAttribute && + z.Attribute.Value.Contains(dateOfBirthStr)) + .Select(z => z.Customer); + } + //search by company + if (!string.IsNullOrWhiteSpace(company)) + { + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.CompanyAttribute && + z.Attribute.Value.Contains(company)) + .Select(z => z.Customer); + } + //search by phone + if (!string.IsNullOrWhiteSpace(phone)) + { + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.PhoneAttribute && + z.Attribute.Value.Contains(phone)) + .Select(z => z.Customer); + } + //search by zip + if (!string.IsNullOrWhiteSpace(zipPostalCode)) + { + query = query + .Join(_genericAttributeRepository.Table, x => x.Id, y => y.EntityId, (x, y) => new { Customer = x, Attribute = y }) + .Where(z => z.Attribute.KeyGroup == nameof(Customer) && + z.Attribute.Key == NopCustomerDefaults.ZipPostalCodeAttribute && + z.Attribute.Value.Contains(zipPostalCode)) + .Select(z => z.Customer); + } + + //search by IpAddress + if (!string.IsNullOrWhiteSpace(ipAddress) && CommonHelper.IsValidIpAddress(ipAddress)) + { + query = query.Where(w => w.LastIpAddress == ipAddress); + } + + query = query.OrderByDescending(c => c.CreatedOnUtc); + + return query; + } + + public IList GetCustomersDtos(DateTime? createdAtMin = null, + DateTime? createdAtMax = null, + int limit = Configurations.DefaultLimit, + int page = Configurations.DefaultPageValue, + int sinceId = Configurations.DefaultSinceId) + { + var result = new List(); + + var roleIds = _customerRoleRepository.Table.Where(o => o.SystemName != NopCustomerDefaults.GuestsRoleName) + .Select(o => o.Id) + .ToArray(); + + var customerAttributes = _genericAttributeRepository.Table.Where(o => o.KeyGroup == nameof(Customer)); + + var customerWithAttributes = GetAllCustomers(createdAtMin, createdAtMax, customerRoleIds: roleIds, pageIndex: page - 1, pageSize: limit) + .ToList() + .GroupJoin(customerAttributes, outer => outer.Id, inner => inner.EntityId, (o, i) => new + { + Customer = o, + Attributes = i + }); + + result.AddRange(customerWithAttributes.Select(o => CreateCustomerDto(o.Customer, o.Attributes))); + + SetNewsletterSubscriptionStatus(result); + + + return result; + } + + private CustomerDto CreateCustomerDto(Customer customer, IEnumerable customerAttributes) + { + var customerDto = customer.ToDto(); + foreach (var attribute in customerAttributes) + { + + if (attribute.Key.Equals(FirstName, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.FirstName = attribute.Value; + } + else if (attribute.Key.Equals(LastName, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.LastName = attribute.Value; + } + else if (attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.LanguageId = attribute.Value; + } + else if (attribute.Key.Equals(DateOfBirth, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.DateOfBirth = string.IsNullOrEmpty(attribute.Value) ? (DateTime?)null : DateTime.Parse(attribute.Value); + } + else if (attribute.Key.Equals(Gender, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.Gender = attribute.Value; + } + } + return customerDto; + } + + public int GetCustomersCount() + { + return _customerRepository.Table.Count(customer => !customer.Deleted + && (customer.RegisteredInStoreId == 0 || customer.RegisteredInStoreId == _storeContext.CurrentStore.Id)); + } + + // Need to work with dto object so we can map the first and last name from generic attributes table. + public IList Search(string queryParams = "", string order = Configurations.DefaultOrder, + int page = Configurations.DefaultPageValue, int limit = Configurations.DefaultLimit) + { + IList result = new List(); + + var searchParams = EnsureSearchQueryIsValid(queryParams, ParseSearchQuery); + + if (searchParams != null) + { + var query = _customerRepository.Table.Where(customer => !customer.Deleted); + + foreach (var searchParam in searchParams) + { + // Skip non existing properties. + if (ReflectionHelper.HasProperty(searchParam.Key, typeof(Customer))) + { + + // @0 is a placeholder used by dynamic linq and it is used to prevent possible sql injections. + query = query.Where(string.Format("{0} = @0 || {0}.Contains(@0)", searchParam.Key), searchParam.Value); + } + // The code bellow will search in customer addresses as well. + //else if (HasProperty(searchParam.Key, typeof(Address))) + //{ + // query = query.Where(string.Format("Addresses.Where({0} == @0).Any()", searchParam.Key), searchParam.Value); + //} + } + + //result = HandleCustomerGenericAttributes(searchParams, query, limit, page, order); + } + + return result; + } + + public Customer GetCustomerEntityById(int id) + { + var customer = _customerRepository.Table.FirstOrDefault(c => c.Id == id && !c.Deleted); + + return customer; + } + + public CustomerDto GetCustomerById(int id, bool showDeleted = false) + { + if (id == 0) + return null; + + // Here we expect to get two records, one for the first name and one for the last name. + var customerAttributeMappings = (from customer in _customerRepository.Table //NoTracking + join attribute in _genericAttributeRepository.Table//NoTracking + on customer.Id equals attribute.EntityId + where customer.Id == id && + attribute.KeyGroup == "Customer" + select new CustomerAttributeMappingDto + { + Attribute = attribute, + Customer = customer + }).ToList(); + + CustomerDto customerDto = null; + + // This is in case we have first and last names set for the customer. + if (customerAttributeMappings.Count > 0) + { + var customer = customerAttributeMappings.First().Customer; + // The customer object is the same in all mappings. + customerDto = customer.ToDto(); + + var customerRoles = _customerService.GetCustomerRoles(customer); + foreach (var role in customerRoles) + customerDto.RoleIds.Add(role.Id); + + var defaultStoreLanguageId = GetDefaultStoreLangaugeId(); + + // If there is no Language Id generic attribute create one with the default language id. + if (!customerAttributeMappings.Any(cam => cam?.Attribute != null && cam.Attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase))) + { + var languageId = new GenericAttribute + { + Key = LanguageId, + Value = defaultStoreLanguageId.ToString() + }; + + var customerAttributeMappingDto = new CustomerAttributeMappingDto + { + Customer = customer, + Attribute = languageId + }; + + customerAttributeMappings.Add(customerAttributeMappingDto); + } + + foreach (var mapping in customerAttributeMappings) + { + if (!showDeleted && mapping.Customer.Deleted) + { + continue; + } + + if (mapping.Attribute != null) + { + if (mapping.Attribute.Key.Equals(FirstName, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.FirstName = mapping.Attribute.Value; + } + else if (mapping.Attribute.Key.Equals(LastName, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.LastName = mapping.Attribute.Value; + } + else if (mapping.Attribute.Key.Equals(LanguageId, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.LanguageId = mapping.Attribute.Value; + } + else if (mapping.Attribute.Key.Equals(DateOfBirth, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.DateOfBirth = string.IsNullOrEmpty(mapping.Attribute.Value) ? (DateTime?)null : DateTime.Parse(mapping.Attribute.Value); + } + else if (mapping.Attribute.Key.Equals(Gender, StringComparison.InvariantCultureIgnoreCase)) + { + customerDto.Gender = mapping.Attribute.Value; + } + } + } + } + else + { + // This is when we do not have first and last name set. + var currentCustomer = _customerRepository.Table.FirstOrDefault(customer => customer.Id == id); + + if (currentCustomer != null) + { + if (showDeleted || !currentCustomer.Deleted) + { + customerDto = currentCustomer.ToDto(); + } + } + } + + SetNewsletterSubscriptionStatus(customerDto); + + return customerDto; + } + + private Dictionary EnsureSearchQueryIsValid(string query, Func> parseSearchQuery) + { + if (!string.IsNullOrEmpty(query)) + { + return parseSearchQuery(query); + } + + return null; + } + + private Dictionary ParseSearchQuery(string query) + { + var parsedQuery = new Dictionary(); + + var splitPattern = @"(\w+):"; + + var fieldValueList = Regex.Split(query, splitPattern).Where(s => s != String.Empty).ToList(); + + if (fieldValueList.Count < 2) + { + return parsedQuery; + } + + for (var i = 0; i < fieldValueList.Count; i += 2) + { + var field = fieldValueList[i]; + var value = fieldValueList[i + 1]; + + if (!string.IsNullOrEmpty(field) && !string.IsNullOrEmpty(value)) + { + field = field.Replace("_", string.Empty); + parsedQuery.Add(field.Trim(), value.Trim()); + } + } + + return parsedQuery; + } + + private int GetDefaultStoreLangaugeId() + { + // Get the default language id for the current store. + var defaultLanguageId = _storeContext.CurrentStore.DefaultLanguageId; + + if (defaultLanguageId == 0) + { + var allLanguages = _languageService.GetAllLanguages(); + + var storeLanguages = allLanguages.Where(l => + _storeMappingService.Authorize(l, _storeContext.CurrentStore.Id)).ToList(); + + // If there is no language mapped to the current store, get all of the languages, + // and use the one with the first display order. This is a default nopCommerce workflow. + if (storeLanguages.Count == 0) + { + storeLanguages = allLanguages.ToList(); + } + + var defaultLanguage = storeLanguages.OrderBy(l => l.DisplayOrder).First(); + + defaultLanguageId = defaultLanguage.Id; + } + + return defaultLanguageId; + } + + [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] + private void SetNewsletterSubscriptionStatus(IEnumerable customerDtos) + { + if (customerDtos == null) + { + return; + } + + var allNewsletterCustomerEmail = GetAllNewsletterCustomersEmails(); + + foreach (var customerDto in customerDtos) + { + SetNewsletterSubscriptionStatus(customerDto, allNewsletterCustomerEmail); + } + } + + private void SetNewsletterSubscriptionStatus(BaseCustomerDto customerDto, IEnumerable allNewsletterCustomerEmail = null) + { + if (customerDto == null || String.IsNullOrEmpty(customerDto.Email)) + { + return; + } + + if (allNewsletterCustomerEmail == null) + { + allNewsletterCustomerEmail = GetAllNewsletterCustomersEmails(); + } + + if (allNewsletterCustomerEmail != null && allNewsletterCustomerEmail.Contains(customerDto.Email.ToLowerInvariant())) + { + customerDto.SubscribedToNewsletter = true; + } + } + + private IEnumerable GetAllNewsletterCustomersEmails() + { + return _cacheManager.Get(Configurations.NEWSLETTER_SUBSCRIBERS_KEY, () => + { + IEnumerable subscriberEmails = (from nls in _subscriptionRepository.Table + where nls.StoreId == _storeContext.CurrentStore.Id + && nls.Active + select nls.Email).ToList(); + + + subscriberEmails = subscriberEmails.Where(e => !String.IsNullOrEmpty(e)).Select(e => e.ToLowerInvariant()); + + return subscriberEmails.Where(e => !String.IsNullOrEmpty(e)).Select(e => e.ToLowerInvariant()); + }); + } + } +} + diff --git a/Nop.Plugin.Api/Services/ICategoryApiService.cs b/Services/ICategoryApiService.cs similarity index 88% rename from Nop.Plugin.Api/Services/ICategoryApiService.cs rename to Services/ICategoryApiService.cs index f47366d..bdb08a3 100644 --- a/Nop.Plugin.Api/Services/ICategoryApiService.cs +++ b/Services/ICategoryApiService.cs @@ -1,7 +1,7 @@ -using System; +using Nop.Core.Domain.Catalog; +using System; using System.Collections.Generic; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IClientService.cs b/Services/IClientService.cs similarity index 78% rename from Nop.Plugin.Api/Services/IClientService.cs rename to Services/IClientService.cs index 8e448da..cc2dcc1 100644 --- a/Nop.Plugin.Api/Services/IClientService.cs +++ b/Services/IClientService.cs @@ -1,16 +1,17 @@ -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Services -{ - using Models; - - public interface IClientService - { - IList GetAllClients(); - void DeleteClient(int id); - int InsertClient(ClientApiModel model); - void UpdateClient(ClientApiModel model); - ClientApiModel FindClientByIdAsync(int id); - ClientApiModel FindClientByClientId(string clientId); - } +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Services +{ + using Models; + using Nop.Web.Framework.Models; + + public interface IClientService + { + ClientApiListModel GetAllClients(ClientApiSearchModel model); + void DeleteClient(int id); + int InsertClient(ClientApiModel model); + void UpdateClient(ClientApiModel model); + ClientApiModel FindClientByIdAsync(int id); + ClientApiModel FindClientByClientId(string clientId); + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/ICustomerApiService.cs b/Services/ICustomerApiService.cs similarity index 78% rename from Nop.Plugin.Api/Services/ICustomerApiService.cs rename to Services/ICustomerApiService.cs index 4e4683c..a26c2a0 100644 --- a/Nop.Plugin.Api/Services/ICustomerApiService.cs +++ b/Services/ICustomerApiService.cs @@ -1,8 +1,8 @@ -using System; +using Nop.Core.Domain.Customers; +using Nop.Plugin.Api.DTO.Customers; +using System; using System.Collections.Generic; -using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DTOs.Customers; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { @@ -20,6 +20,5 @@ IList GetCustomersDtos(DateTime? createdAtMin = null, DateTime? cre IList Search(string query = "", string order = Configurations.DefaultOrder, int page = Configurations.DefaultPageValue, int limit = Configurations.DefaultLimit); - Dictionary GetFirstAndLastNameByCustomerId(int customerId); } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/IManufacturerApiService.cs b/Services/IManufacturerApiService.cs similarity index 89% rename from Nop.Plugin.Api/Services/IManufacturerApiService.cs rename to Services/IManufacturerApiService.cs index 6875587..5cdfc37 100644 --- a/Nop.Plugin.Api/Services/IManufacturerApiService.cs +++ b/Services/IManufacturerApiService.cs @@ -1,7 +1,7 @@ -using System; +using Nop.Core.Domain.Catalog; +using System; using System.Collections.Generic; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/INewsLetterSubscriptionApiService.cs b/Services/INewsLetterSubscriptionApiService.cs similarity index 90% rename from Nop.Plugin.Api/Services/INewsLetterSubscriptionApiService.cs rename to Services/INewsLetterSubscriptionApiService.cs index 20d55a0..dd19a9c 100644 --- a/Nop.Plugin.Api/Services/INewsLetterSubscriptionApiService.cs +++ b/Services/INewsLetterSubscriptionApiService.cs @@ -1,7 +1,7 @@ using Nop.Core.Domain.Messages; -using Nop.Plugin.Api.Constants; using System; using System.Collections.Generic; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IOrderApiService.cs b/Services/IOrderApiService.cs similarity index 87% rename from Nop.Plugin.Api/Services/IOrderApiService.cs rename to Services/IOrderApiService.cs index 8d4684e..8744be7 100644 --- a/Nop.Plugin.Api/Services/IOrderApiService.cs +++ b/Services/IOrderApiService.cs @@ -1,9 +1,9 @@ -using System; -using System.Collections.Generic; -using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Orders; using Nop.Core.Domain.Payments; using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Constants; +using System; +using System.Collections.Generic; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { @@ -20,6 +20,6 @@ IList GetOrders(IList ids = null, DateTime? createdAtMin = null, Dat int GetOrdersCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, OrderStatus? status = null, PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, - int? customerId = null, int? storeId = null); + int? customerId = null, int? storeId = null, int sinceId = Configurations.DefaultSinceId); } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/IOrderItemApiService.cs b/Services/IOrderItemApiService.cs similarity index 100% rename from Nop.Plugin.Api/Services/IOrderItemApiService.cs rename to Services/IOrderItemApiService.cs diff --git a/Nop.Plugin.Api/Services/IProductApiService.cs b/Services/IProductApiService.cs similarity index 94% rename from Nop.Plugin.Api/Services/IProductApiService.cs rename to Services/IProductApiService.cs index 6d0f005..9f062a6 100644 --- a/Nop.Plugin.Api/Services/IProductApiService.cs +++ b/Services/IProductApiService.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; + namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IProductAttributeConverter.cs b/Services/IProductAttributeConverter.cs similarity index 90% rename from Nop.Plugin.Api/Services/IProductAttributeConverter.cs rename to Services/IProductAttributeConverter.cs index 5b8b933..2f09d3b 100644 --- a/Nop.Plugin.Api/Services/IProductAttributeConverter.cs +++ b/Services/IProductAttributeConverter.cs @@ -1,4 +1,4 @@ -using Nop.Plugin.Api.DTOs; +using Nop.Plugin.Api.DTO; using System.Collections.Generic; namespace Nop.Plugin.Api.Services diff --git a/Nop.Plugin.Api/Services/IProductAttributesApiService.cs b/Services/IProductAttributesApiService.cs similarity index 89% rename from Nop.Plugin.Api/Services/IProductAttributesApiService.cs rename to Services/IProductAttributesApiService.cs index b7ade53..9b25e2c 100644 --- a/Nop.Plugin.Api/Services/IProductAttributesApiService.cs +++ b/Services/IProductAttributesApiService.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IProductCategoryMappingsApiService.cs b/Services/IProductCategoryMappingsApiService.cs similarity index 90% rename from Nop.Plugin.Api/Services/IProductCategoryMappingsApiService.cs rename to Services/IProductCategoryMappingsApiService.cs index f81f995..f937935 100644 --- a/Nop.Plugin.Api/Services/IProductCategoryMappingsApiService.cs +++ b/Services/IProductCategoryMappingsApiService.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IProductManufacturerMappingsApiService.cs b/Services/IProductManufacturerMappingsApiService.cs similarity index 91% rename from Nop.Plugin.Api/Services/IProductManufacturerMappingsApiService.cs rename to Services/IProductManufacturerMappingsApiService.cs index eca7627..5d077a7 100644 --- a/Nop.Plugin.Api/Services/IProductManufacturerMappingsApiService.cs +++ b/Services/IProductManufacturerMappingsApiService.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/IProductPictureService.cs b/Services/IProductPictureService.cs similarity index 100% rename from Nop.Plugin.Api/Services/IProductPictureService.cs rename to Services/IProductPictureService.cs diff --git a/Nop.Plugin.Api/Services/IShoppingCartItemApiService.cs b/Services/IShoppingCartItemApiService.cs similarity index 92% rename from Nop.Plugin.Api/Services/IShoppingCartItemApiService.cs rename to Services/IShoppingCartItemApiService.cs index f675fc2..6762125 100644 --- a/Nop.Plugin.Api/Services/IShoppingCartItemApiService.cs +++ b/Services/IShoppingCartItemApiService.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/ISpecificationAttributeApiService.cs b/Services/ISpecificationAttributeApiService.cs similarity index 92% rename from Nop.Plugin.Api/Services/ISpecificationAttributeApiService.cs rename to Services/ISpecificationAttributeApiService.cs index 052a015..27b6157 100644 --- a/Nop.Plugin.Api/Services/ISpecificationAttributeApiService.cs +++ b/Services/ISpecificationAttributeApiService.cs @@ -1,5 +1,5 @@ using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using static Nop.Plugin.Api.Infrastructure.Constants; using System.Collections.Generic; namespace Nop.Plugin.Api.Services diff --git a/Nop.Plugin.Api/Services/IWebHookService.cs b/Services/IWebHookService.cs similarity index 96% rename from Nop.Plugin.Api/Services/IWebHookService.cs rename to Services/IWebHookService.cs index e4e7463..f08750c 100644 --- a/Nop.Plugin.Api/Services/IWebHookService.cs +++ b/Services/IWebHookService.cs @@ -1,12 +1,12 @@ -//namespace Nop.Plugin.Api.Services -//{ -// using Microsoft.AspNet.WebHooks; - -// public interface IWebHookService -// { -// IWebHookManager GetWebHookManager(); -// IWebHookSender GetWebHookSender(); -// IWebHookStore GetWebHookStore(); -// IWebHookFilterManager GetWebHookFilterManager(); -// } -//} +//namespace Nop.Plugin.Api.Services +//{ +// using Microsoft.AspNet.WebHooks; + +// public interface IWebHookService +// { +// IWebHookManager GetWebHookManager(); +// IWebHookSender GetWebHookSender(); +// IWebHookStore GetWebHookStore(); +// IWebHookFilterManager GetWebHookFilterManager(); +// } +//} diff --git a/Nop.Plugin.Api/Services/ManufacturerApiService.cs b/Services/ManufacturerApiService.cs similarity index 79% rename from Nop.Plugin.Api/Services/ManufacturerApiService.cs rename to Services/ManufacturerApiService.cs index edbe708..071a645 100644 --- a/Nop.Plugin.Api/Services/ManufacturerApiService.cs +++ b/Services/ManufacturerApiService.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Localization; -using Nop.Plugin.Api.Constants; +using Nop.Data; using Nop.Plugin.Api.DataStructures; -using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { @@ -25,13 +24,15 @@ public ManufacturerApiService(IRepository manufacturerRepository, _localizedPropertyRepository = localizedPropertyRepository; } - public IList GetManufacturers(IList ids = null, - DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, - int? productId = null, bool? publishedStatus = null, int? languageId = null) + public IList GetManufacturers( + IList ids = null, + DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, + int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, + int sinceId = Configurations.DefaultSinceId, + int? productId = null, bool? publishedStatus = null, int? languageId = null) { var query = GetManufacturersQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, publishedStatus, productId, ids); - + if (sinceId > 0) { query = query.Where(c => c.Id > sinceId); @@ -40,13 +41,15 @@ public IList GetManufacturers(IList ids = null, if (languageId.HasValue) { - var localizedNames = _localizedPropertyRepository.TableNoTracking.Where(x => x.LocaleKeyGroup == "Manufacturer" && languageId == languageId.Value); - foreach (var cat in list) - { - var localizedName = localizedNames.FirstOrDefault(x => x.EntityId == cat.Id); - if (localizedName != null) - cat.Name = localizedName.LocaleValue; - } + //var localizedNames = _localizedPropertyRepository.TableNoTracking.Where(x => x.LocaleKeyGroup == "Manufacturer" && languageId == languageId.Value); + //foreach (var cat in list) + //{ + // var localizedName = localizedNames.FirstOrDefault(x => x.EntityId == cat.Id); + // if (localizedName != null) + // { + // cat.Name = localizedName.LocaleValue; + // } + //} } return list; diff --git a/Nop.Plugin.Api/Services/NewsLetterSubscriptionApiService.cs b/Services/NewsLetterSubscriptionApiService.cs similarity index 93% rename from Nop.Plugin.Api/Services/NewsLetterSubscriptionApiService.cs rename to Services/NewsLetterSubscriptionApiService.cs index dcd5c20..5a21fa0 100644 --- a/Nop.Plugin.Api/Services/NewsLetterSubscriptionApiService.cs +++ b/Services/NewsLetterSubscriptionApiService.cs @@ -1,62 +1,62 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core; -using Nop.Core.Data; -using Nop.Core.Domain.Messages; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; - -namespace Nop.Plugin.Api.Services -{ - public class NewsLetterSubscriptionApiService : INewsLetterSubscriptionApiService - { - private readonly IRepository _newsLetterSubscriptionRepository; - private readonly IStoreContext _storeContext; - - public NewsLetterSubscriptionApiService(IRepository newsLetterSubscriptionRepository, IStoreContext storeContext) - { - _newsLetterSubscriptionRepository = newsLetterSubscriptionRepository; - _storeContext = storeContext; - } - - public List GetNewsLetterSubscriptions(DateTime? createdAtMin = null, DateTime? createdAtMax = null, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, - bool? onlyActive = true) - { - var query = GetNewsLetterSubscriptionsQuery(createdAtMin, createdAtMax, onlyActive); - - if (sinceId > 0) - { - query = query.Where(c => c.Id > sinceId); - } - - return new ApiList(query, page - 1, limit); - } - - private IQueryable GetNewsLetterSubscriptionsQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, bool? onlyActive = true) - { - var query = _newsLetterSubscriptionRepository.Table.Where(nls => nls.StoreId == _storeContext.CurrentStore.Id); - - if (onlyActive != null && onlyActive == true) - { - query = query.Where(nls => nls.Active == onlyActive); - } - - if (createdAtMin != null) - { - query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); - } - - if (createdAtMax != null) - { - - query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); - } - - query = query.OrderBy(nls => nls.Id); - - return query; - } - } -} +using Nop.Core; +using Nop.Core.Domain.Messages; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class NewsLetterSubscriptionApiService : INewsLetterSubscriptionApiService + { + private readonly IRepository _newsLetterSubscriptionRepository; + private readonly IStoreContext _storeContext; + + public NewsLetterSubscriptionApiService(IRepository newsLetterSubscriptionRepository, IStoreContext storeContext) + { + _newsLetterSubscriptionRepository = newsLetterSubscriptionRepository; + _storeContext = storeContext; + } + + public List GetNewsLetterSubscriptions(DateTime? createdAtMin = null, DateTime? createdAtMax = null, + int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, + bool? onlyActive = true) + { + var query = GetNewsLetterSubscriptionsQuery(createdAtMin, createdAtMax, onlyActive); + + if (sinceId > 0) + { + query = query.Where(c => c.Id > sinceId); + } + + return new ApiList(query, page - 1, limit); + } + + private IQueryable GetNewsLetterSubscriptionsQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, bool? onlyActive = true) + { + var query = _newsLetterSubscriptionRepository.Table.Where(nls => nls.StoreId == _storeContext.CurrentStore.Id); + + if (onlyActive != null && onlyActive == true) + { + query = query.Where(nls => nls.Active == onlyActive); + } + + if (createdAtMin != null) + { + query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); + } + + if (createdAtMax != null) + { + + query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); + } + + query = query.OrderBy(nls => nls.Id); + + return query; + } + } +} diff --git a/Nop.Plugin.Api/Services/OrderApiService.cs b/Services/OrderApiService.cs similarity index 92% rename from Nop.Plugin.Api/Services/OrderApiService.cs rename to Services/OrderApiService.cs index 56b2d9b..3f89d8d 100644 --- a/Nop.Plugin.Api/Services/OrderApiService.cs +++ b/Services/OrderApiService.cs @@ -1,128 +1,132 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Core.Domain.Payments; -using Nop.Core.Domain.Shipping; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; - -namespace Nop.Plugin.Api.Services -{ - public class OrderApiService : IOrderApiService - { - private readonly IRepository _orderRepository; - - public OrderApiService(IRepository orderRepository) - { - _orderRepository = orderRepository; - } - - public IList GetOrdersByCustomerId(int customerId) - { - var query = from order in _orderRepository.Table - where order.CustomerId == customerId && !order.Deleted - orderby order.Id - select order; - - return new ApiList(query, 0, Configurations.MaxLimit); - } - - public IList GetOrders(IList ids = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, - OrderStatus? status = null, PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, int? customerId = null, - int? storeId = null) - { - var query = GetOrdersQuery(createdAtMin, createdAtMax, status, paymentStatus, shippingStatus, ids, customerId, storeId); - - if (sinceId > 0) - { - query = query.Where(order => order.Id > sinceId); - } - - return new ApiList(query, page - 1, limit); - } - - public Order GetOrderById(int orderId) - { - if (orderId <= 0) - return null; - - return _orderRepository.Table.FirstOrDefault(order => order.Id == orderId && !order.Deleted); - } - - public int GetOrdersCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, OrderStatus? status = null, - PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, - int? customerId = null, int? storeId = null) - { - var query = GetOrdersQuery(createdAtMin, createdAtMax, status, paymentStatus, shippingStatus, customerId: customerId, storeId: storeId); - - return query.Count(); - } - - private IQueryable GetOrdersQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, OrderStatus? status = null, - PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, IList ids = null, - int? customerId = null, int? storeId = null) - { - var query = _orderRepository.Table; - - if (customerId != null) - { - query = query.Where(order => order.CustomerId == customerId); - } - - if (ids != null && ids.Count > 0) - { - query = query.Where(c => ids.Contains(c.Id)); - } - - if (status != null) - { - query = query.Where(order => order.OrderStatusId == (int)status); - } - - if (paymentStatus != null) - { - query = query.Where(order => order.PaymentStatusId == (int)paymentStatus); - } - - if (shippingStatus != null) - { - query = query.Where(order => order.ShippingStatusId == (int)shippingStatus); - } - - query = query.Where(order => !order.Deleted); - - if (createdAtMin != null) - { - query = query.Where(order => order.CreatedOnUtc > createdAtMin.Value.ToUniversalTime()); - } - - if (createdAtMax != null) - { - query = query.Where(order => order.CreatedOnUtc < createdAtMax.Value.ToUniversalTime()); - } - - if (storeId != null) - { - query = query.Where(order => order.StoreId == storeId); - } - - query = query.OrderBy(order => order.Id); - - //query = query.Include(c => c.Customer); - //query = query.Include(c => c.BillingAddress); - //query = query.Include(c => c.ShippingAddress); - //query = query.Include(c => c.PickupAddress); - //query = query.Include(c => c.RedeemedRewardPointsEntry); - //query = query.Include(c => c.DiscountUsageHistory); - //query = query.Include(c => c.GiftCardUsageHistory); - //query = query.Include(c => c.OrderNotes); - //query = query.Include(c => c.OrderItems); - //query = query.Include(c => c.Shipments); - - return query; - } - } +using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Payments; +using Nop.Core.Domain.Shipping; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class OrderApiService : IOrderApiService + { + private readonly IRepository _orderRepository; + + public OrderApiService(IRepository orderRepository) + { + _orderRepository = orderRepository; + } + + public IList GetOrdersByCustomerId(int customerId) + { + var query = from order in _orderRepository.Table + where order.CustomerId == customerId && !order.Deleted + orderby order.Id + select order; + + return new ApiList(query, 0, Configurations.MaxLimit); + } + + public IList GetOrders(IList ids = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, + int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, + OrderStatus? status = null, PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, int? customerId = null, + int? storeId = null) + { + var query = GetOrdersQuery(createdAtMin, createdAtMax, status, paymentStatus, shippingStatus, ids, customerId, storeId); + + if (sinceId > 0) + { + query = query.Where(order => order.Id > sinceId); + } + + return new ApiList(query, page - 1, limit); + } + + public Order GetOrderById(int orderId) + { + if (orderId <= 0) + return null; + + return _orderRepository.Table.FirstOrDefault(order => order.Id == orderId && !order.Deleted); + } + + public int GetOrdersCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, OrderStatus? status = null, + PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, + int? customerId = null, int? storeId = null, int sinceId = Configurations.DefaultSinceId) + { + var query = GetOrdersQuery(createdAtMin, createdAtMax, status, paymentStatus, shippingStatus, customerId: customerId, storeId: storeId); + + if (sinceId > 0) + { + query = query.Where(order => order.Id > sinceId); + } + + return query.Count(); + } + + private IQueryable GetOrdersQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, OrderStatus? status = null, + PaymentStatus? paymentStatus = null, ShippingStatus? shippingStatus = null, IList ids = null, + int? customerId = null, int? storeId = null) + { + var query = _orderRepository.Table.Where(order => !order.Deleted); + + if (customerId != null) + { + query = query.Where(order => order.CustomerId == customerId); + } + + if (ids != null && ids.Count > 0) + { + query = query.Where(c => ids.Contains(c.Id)); + } + + if (status != null) + { + query = query.Where(order => order.OrderStatusId == (int)status); + } + + if (paymentStatus != null) + { + query = query.Where(order => order.PaymentStatusId == (int)paymentStatus); + } + + if (shippingStatus != null) + { + query = query.Where(order => order.ShippingStatusId == (int)shippingStatus); + } + + + if (createdAtMin != null) + { + query = query.Where(order => order.CreatedOnUtc > createdAtMin.Value.ToUniversalTime()); + } + + if (createdAtMax != null) + { + query = query.Where(order => order.CreatedOnUtc < createdAtMax.Value.ToUniversalTime()); + } + + if (storeId != null) + { + query = query.Where(order => order.StoreId == storeId); + } + + query = query.OrderBy(order => order.Id); + + //query = query.Include(c => c.Customer); + //query = query.Include(c => c.BillingAddress); + //query = query.Include(c => c.ShippingAddress); + //query = query.Include(c => c.PickupAddress); + //query = query.Include(c => c.RedeemedRewardPointsEntry); + //query = query.Include(c => c.DiscountUsageHistory); + //query = query.Include(c => c.GiftCardUsageHistory); + //query = query.Include(c => c.OrderNotes); + //query = query.Include(c => c.OrderItems); + //query = query.Include(c => c.Shipments); + + return query; + } + } } \ No newline at end of file diff --git a/Services/OrderItemApiService.cs b/Services/OrderItemApiService.cs new file mode 100644 index 0000000..011128a --- /dev/null +++ b/Services/OrderItemApiService.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using Nop.Core.Domain.Orders; +using Nop.Plugin.Api.DataStructures; +using Nop.Services.Catalog; +using Nop.Services.Orders; + +namespace Nop.Plugin.Api.Services +{ + public class OrderItemApiService : IOrderItemApiService + { + private readonly IOrderService _orderService; + private readonly IProductService _productService; + + public OrderItemApiService(IOrderService orderService + , IProductService productService) + { + _orderService = orderService; + _productService = productService; + } + public IList GetOrderItemsForOrder(Order order, int limit, int page, int sinceId) + { + var orderItems = _orderService.GetOrderItems(order.Id).AsQueryable(); + + return new ApiList(orderItems, page - 1, limit); + } + + public int GetOrderItemsCount(Order order) + { + var orderItemsCount = _orderService.GetOrderItems(order.Id).Count(); + + return orderItemsCount; + } + + } +} diff --git a/Nop.Plugin.Api/Services/ProductApiService.cs b/Services/ProductApiService.cs similarity index 95% rename from Nop.Plugin.Api/Services/ProductApiService.cs rename to Services/ProductApiService.cs index 0a55e9e..f6eefe5 100644 --- a/Nop.Plugin.Api/Services/ProductApiService.cs +++ b/Services/ProductApiService.cs @@ -1,136 +1,136 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Core.Domain.Vendors; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; -using Nop.Services.Stores; - -namespace Nop.Plugin.Api.Services -{ - public class ProductApiService : IProductApiService - { - private readonly IStoreMappingService _storeMappingService; - private readonly IRepository _productRepository; - private readonly IRepository _productCategoryMappingRepository; - private readonly IRepository _vendorRepository; - - public ProductApiService(IRepository productRepository, - IRepository productCategoryMappingRepository, - IRepository vendorRepository, - IStoreMappingService storeMappingService) - { - _productRepository = productRepository; - _productCategoryMappingRepository = productCategoryMappingRepository; - _vendorRepository = vendorRepository; - _storeMappingService = storeMappingService; - } - - public IList GetProducts(IList ids = null, - DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, - int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, - int? categoryId = null, string vendorName = null, bool? publishedStatus = null) - { - var query = GetProductsQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, vendorName, publishedStatus, ids, categoryId); - - if (sinceId > 0) - { - query = query.Where(c => c.Id > sinceId); - } - - return new ApiList(query, page - 1, limit); - } - - public int GetProductsCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, - DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, bool? publishedStatus = null, string vendorName = null, - int? categoryId = null) - { - var query = GetProductsQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, vendorName, - publishedStatus, categoryId: categoryId); - - return query.ToList().Count(p => _storeMappingService.Authorize(p)); - } - - public Product GetProductById(int productId) - { - if (productId == 0) - return null; - - return _productRepository.Table.FirstOrDefault(product => product.Id == productId && !product.Deleted); - } - - public Product GetProductByIdNoTracking(int productId) - { - if (productId == 0) - return null; - - return _productRepository.Table.FirstOrDefault(product => product.Id == productId && !product.Deleted); - } - - private IQueryable GetProductsQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, - DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, string vendorName = null, - bool? publishedStatus = null, IList ids = null, int? categoryId = null) - - { - var query = _productRepository.Table; - - if (ids != null && ids.Count > 0) - { - query = query.Where(c => ids.Contains(c.Id)); - } - - if (publishedStatus != null) - { - query = query.Where(c => c.Published == publishedStatus.Value); - } - - // always return products that are not deleted!!! - query = query.Where(c => !c.Deleted); - - if (createdAtMin != null) - { - query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); - } - - if (createdAtMax != null) - { - query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); - } - - if (updatedAtMin != null) - { - query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); - } - - if (updatedAtMax != null) - { - query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); - } - - if (!string.IsNullOrEmpty(vendorName)) - { - query = from vendor in _vendorRepository.Table - join product in _productRepository.Table on vendor.Id equals product.VendorId - where vendor.Name == vendorName && !vendor.Deleted && vendor.Active - select product; - } - - if (categoryId != null) - { - var categoryMappingsForProduct = from productCategoryMapping in _productCategoryMappingRepository.Table - where productCategoryMapping.CategoryId == categoryId - select productCategoryMapping; - - query = from product in query - join productCategoryMapping in categoryMappingsForProduct on product.Id equals productCategoryMapping.ProductId - select product; - } - - query = query.OrderBy(product => product.Id); - - return query; - } - } +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Vendors; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using Nop.Services.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class ProductApiService : IProductApiService + { + private readonly IStoreMappingService _storeMappingService; + private readonly IRepository _productRepository; + private readonly IRepository _productCategoryMappingRepository; + private readonly IRepository _vendorRepository; + + public ProductApiService(IRepository productRepository, + IRepository productCategoryMappingRepository, + IRepository vendorRepository, + IStoreMappingService storeMappingService) + { + _productRepository = productRepository; + _productCategoryMappingRepository = productCategoryMappingRepository; + _vendorRepository = vendorRepository; + _storeMappingService = storeMappingService; + } + + public IList GetProducts(IList ids = null, + DateTime? createdAtMin = null, DateTime? createdAtMax = null, DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, + int limit = Configurations.DefaultLimit, int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId, + int? categoryId = null, string vendorName = null, bool? publishedStatus = null) + { + var query = GetProductsQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, vendorName, publishedStatus, ids, categoryId); + + if (sinceId > 0) + { + query = query.Where(c => c.Id > sinceId); + } + + return new ApiList(query, page - 1, limit); + } + + public int GetProductsCount(DateTime? createdAtMin = null, DateTime? createdAtMax = null, + DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, bool? publishedStatus = null, string vendorName = null, + int? categoryId = null) + { + var query = GetProductsQuery(createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, vendorName, + publishedStatus, categoryId: categoryId); + + return query.ToList().Count(p => _storeMappingService.Authorize(p)); + } + + public Product GetProductById(int productId) + { + if (productId == 0) + return null; + + return _productRepository.Table.FirstOrDefault(product => product.Id == productId && !product.Deleted); + } + + public Product GetProductByIdNoTracking(int productId) + { + if (productId == 0) + return null; + + return _productRepository.Table.FirstOrDefault(product => product.Id == productId && !product.Deleted); + } + + private IQueryable GetProductsQuery(DateTime? createdAtMin = null, DateTime? createdAtMax = null, + DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, string vendorName = null, + bool? publishedStatus = null, IList ids = null, int? categoryId = null) + + { + var query = _productRepository.Table; + + if (ids != null && ids.Count > 0) + { + query = query.Where(c => ids.Contains(c.Id)); + } + + if (publishedStatus != null) + { + query = query.Where(c => c.Published == publishedStatus.Value); + } + + // always return products that are not deleted!!! + query = query.Where(c => !c.Deleted); + + if (createdAtMin != null) + { + query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); + } + + if (createdAtMax != null) + { + query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); + } + + if (updatedAtMin != null) + { + query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); + } + + if (updatedAtMax != null) + { + query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); + } + + if (!string.IsNullOrEmpty(vendorName)) + { + query = from vendor in _vendorRepository.Table + join product in _productRepository.Table on vendor.Id equals product.VendorId + where vendor.Name == vendorName && !vendor.Deleted && vendor.Active + select product; + } + + if (categoryId != null) + { + var categoryMappingsForProduct = from productCategoryMapping in _productCategoryMappingRepository.Table + where productCategoryMapping.CategoryId == categoryId + select productCategoryMapping; + + query = from product in query + join productCategoryMapping in categoryMappingsForProduct on product.Id equals productCategoryMapping.ProductId + select product; + } + + query = query.OrderBy(product => product.Id); + + return query; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/ProductAttributeConverter.cs b/Services/ProductAttributeConverter.cs similarity index 97% rename from Nop.Plugin.Api/Services/ProductAttributeConverter.cs rename to Services/ProductAttributeConverter.cs index 4404035..e21b288 100644 --- a/Nop.Plugin.Api/Services/ProductAttributeConverter.cs +++ b/Services/ProductAttributeConverter.cs @@ -1,189 +1,189 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Plugin.Api.DTOs; -using System.Xml; -using Nop.Services.Catalog; -using Nop.Core.Domain.Catalog; -using Nop.Services.Media; -using Nop.Plugin.Api.Converters; -using System.Globalization; - -namespace Nop.Plugin.Api.Services -{ - public class ProductAttributeConverter : IProductAttributeConverter - { - private readonly IProductAttributeService _productAttributeService; - private readonly IProductAttributeParser _productAttributeParser; - private readonly IDownloadService _downloadService; - - public ProductAttributeConverter(IProductAttributeService productAttributeService, - IProductAttributeParser productAttributeParser, - IDownloadService downloadService, - IApiTypeConverter apiTypeConverter) - { - _productAttributeService = productAttributeService; - _productAttributeParser = productAttributeParser; - _downloadService = downloadService; - } - - public string ConvertToXml(List attributeDtos, int productId) - { - var attributesXml = ""; - - if (attributeDtos == null) - return attributesXml; - - var productAttributes = _productAttributeService.GetProductAttributeMappingsByProductId(productId); - foreach (var attribute in productAttributes) - { - switch (attribute.AttributeControlType) - { - case AttributeControlType.DropdownList: - case AttributeControlType.RadioList: - case AttributeControlType.ColorSquares: - case AttributeControlType.ImageSquares: - { - // there should be only one selected value for this attribute - var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); - if (selectedAttribute != null) - { - int selectedAttributeValue; - var isInt = int.TryParse(selectedAttribute.Value, out selectedAttributeValue); - if (isInt && selectedAttributeValue > 0) - { - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, selectedAttributeValue.ToString()); - } - } - } - break; - case AttributeControlType.Checkboxes: - { - // there could be more than one selected value for this attribute - var selectedAttributes = attributeDtos.Where(x => x.Id == attribute.Id); - foreach (var selectedAttribute in selectedAttributes) - { - int selectedAttributeValue; - var isInt = int.TryParse(selectedAttribute.Value, out selectedAttributeValue); - if (isInt && selectedAttributeValue > 0) - { - // currently there is no support for attribute quantity - var quantity = 1; - - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, selectedAttributeValue.ToString(), quantity); - } - - } - } - break; - case AttributeControlType.ReadonlyCheckboxes: - { - //load read-only(already server - side selected) values - var attributeValues = _productAttributeService.GetProductAttributeValues(attribute.Id); - foreach (var selectedAttributeId in attributeValues - .Where(v => v.IsPreSelected) - .Select(v => v.Id) - .ToList()) - { - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, selectedAttributeId.ToString()); - } - } - break; - case AttributeControlType.TextBox: - case AttributeControlType.MultilineTextbox: - { - var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); - - if (selectedAttribute != null) - { - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, selectedAttribute.Value); - } - - } - break; - case AttributeControlType.Datepicker: - { - var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); - - if (selectedAttribute != null) - { - DateTime selectedDate; - - // Since nopCommerce uses this format to keep the date in the database to keep it consisten we will expect the same format to be passed - var validDate = DateTime.TryParseExact(selectedAttribute.Value, "D", CultureInfo.CurrentCulture, - DateTimeStyles.None, out selectedDate); - - if (validDate) - { - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, selectedDate.ToString("D")); - } - } - } - break; - case AttributeControlType.FileUpload: - { - var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); - - if (selectedAttribute != null) - { - Guid downloadGuid; - Guid.TryParse(selectedAttribute.Value, out downloadGuid); - var download = _downloadService.GetDownloadByGuid(downloadGuid); - if (download != null) - { - attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, - attribute, download.DownloadGuid.ToString()); - } - } - } - break; - default: - break; - } - } - - // No Gift Card attributes support yet - - return attributesXml; - } - - public List Parse(string attributesXml) - { - var attributeDtos = new List(); - if (string.IsNullOrEmpty(attributesXml)) - return attributeDtos; - - try - { - var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(attributesXml); - - foreach (XmlNode attributeNode in xmlDoc.SelectNodes(@"//Attributes/ProductAttribute")) - { - if (attributeNode.Attributes != null && attributeNode.Attributes["ID"] != null) - { - int attributeId; - if (int.TryParse(attributeNode.Attributes["ID"].InnerText.Trim(), out attributeId)) - { - foreach (XmlNode attributeValue in attributeNode.SelectNodes("ProductAttributeValue")) - { - var value = attributeValue.SelectSingleNode("Value").InnerText.Trim(); - // no support for quantity yet - //var quantityNode = attributeValue.SelectSingleNode("Quantity"); - attributeDtos.Add(new ProductItemAttributeDto { Id = attributeId, Value = value }); - } - } - } - } - } - catch { } - - return attributeDtos; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Nop.Plugin.Api.DTO; +using System.Xml; +using Nop.Services.Catalog; +using Nop.Core.Domain.Catalog; +using Nop.Services.Media; +using Nop.Plugin.Api.Converters; +using System.Globalization; + +namespace Nop.Plugin.Api.Services +{ + public class ProductAttributeConverter : IProductAttributeConverter + { + private readonly IProductAttributeService _productAttributeService; + private readonly IProductAttributeParser _productAttributeParser; + private readonly IDownloadService _downloadService; + + public ProductAttributeConverter(IProductAttributeService productAttributeService, + IProductAttributeParser productAttributeParser, + IDownloadService downloadService, + IApiTypeConverter apiTypeConverter) + { + _productAttributeService = productAttributeService; + _productAttributeParser = productAttributeParser; + _downloadService = downloadService; + } + + public string ConvertToXml(List attributeDtos, int productId) + { + var attributesXml = ""; + + if (attributeDtos == null) + return attributesXml; + + var productAttributes = _productAttributeService.GetProductAttributeMappingsByProductId(productId); + foreach (var attribute in productAttributes) + { + switch (attribute.AttributeControlType) + { + case AttributeControlType.DropdownList: + case AttributeControlType.RadioList: + case AttributeControlType.ColorSquares: + case AttributeControlType.ImageSquares: + { + // there should be only one selected value for this attribute + var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); + if (selectedAttribute != null) + { + int selectedAttributeValue; + var isInt = int.TryParse(selectedAttribute.Value, out selectedAttributeValue); + if (isInt && selectedAttributeValue > 0) + { + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, selectedAttributeValue.ToString()); + } + } + } + break; + case AttributeControlType.Checkboxes: + { + // there could be more than one selected value for this attribute + var selectedAttributes = attributeDtos.Where(x => x.Id == attribute.Id); + foreach (var selectedAttribute in selectedAttributes) + { + int selectedAttributeValue; + var isInt = int.TryParse(selectedAttribute.Value, out selectedAttributeValue); + if (isInt && selectedAttributeValue > 0) + { + // currently there is no support for attribute quantity + var quantity = 1; + + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, selectedAttributeValue.ToString(), quantity); + } + + } + } + break; + case AttributeControlType.ReadonlyCheckboxes: + { + //load read-only(already server - side selected) values + var attributeValues = _productAttributeService.GetProductAttributeValues(attribute.Id); + foreach (var selectedAttributeId in attributeValues + .Where(v => v.IsPreSelected) + .Select(v => v.Id) + .ToList()) + { + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, selectedAttributeId.ToString()); + } + } + break; + case AttributeControlType.TextBox: + case AttributeControlType.MultilineTextbox: + { + var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); + + if (selectedAttribute != null) + { + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, selectedAttribute.Value); + } + + } + break; + case AttributeControlType.Datepicker: + { + var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); + + if (selectedAttribute != null) + { + DateTime selectedDate; + + // Since nopCommerce uses this format to keep the date in the database to keep it consisten we will expect the same format to be passed + var validDate = DateTime.TryParseExact(selectedAttribute.Value, "D", CultureInfo.CurrentCulture, + DateTimeStyles.None, out selectedDate); + + if (validDate) + { + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, selectedDate.ToString("D")); + } + } + } + break; + case AttributeControlType.FileUpload: + { + var selectedAttribute = attributeDtos.Where(x => x.Id == attribute.Id).FirstOrDefault(); + + if (selectedAttribute != null) + { + Guid downloadGuid; + Guid.TryParse(selectedAttribute.Value, out downloadGuid); + var download = _downloadService.GetDownloadByGuid(downloadGuid); + if (download != null) + { + attributesXml = _productAttributeParser.AddProductAttribute(attributesXml, + attribute, download.DownloadGuid.ToString()); + } + } + } + break; + default: + break; + } + } + + // No Gift Card attributes support yet + + return attributesXml; + } + + public List Parse(string attributesXml) + { + var attributeDtos = new List(); + if (string.IsNullOrEmpty(attributesXml)) + return attributeDtos; + + try + { + var xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(attributesXml); + + foreach (XmlNode attributeNode in xmlDoc.SelectNodes(@"//Attributes/ProductAttribute")) + { + if (attributeNode.Attributes != null && attributeNode.Attributes["ID"] != null) + { + int attributeId; + if (int.TryParse(attributeNode.Attributes["ID"].InnerText.Trim(), out attributeId)) + { + foreach (XmlNode attributeValue in attributeNode.SelectNodes("ProductAttributeValue")) + { + var value = attributeValue.SelectSingleNode("Value").InnerText.Trim(); + // no support for quantity yet + //var quantityNode = attributeValue.SelectSingleNode("Quantity"); + attributeDtos.Add(new ProductItemAttributeDto { Id = attributeId, Value = value }); + } + } + } + } + } + catch { } + + return attributeDtos; + } + } +} diff --git a/Nop.Plugin.Api/Services/ProductAttributesApiService.cs b/Services/ProductAttributesApiService.cs similarity index 90% rename from Nop.Plugin.Api/Services/ProductAttributesApiService.cs rename to Services/ProductAttributesApiService.cs index 9d8e8ec..41149e2 100644 --- a/Nop.Plugin.Api/Services/ProductAttributesApiService.cs +++ b/Services/ProductAttributesApiService.cs @@ -1,54 +1,54 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; - -namespace Nop.Plugin.Api.Services -{ - public class ProductAttributesApiService : IProductAttributesApiService - { - private readonly IRepository _productAttributesRepository; - - public ProductAttributesApiService(IRepository productAttributesRepository) - { - _productAttributesRepository = productAttributesRepository; - } - - public IList GetProductAttributes(int limit = Configurations.DefaultLimit, - int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId) - { - var query = GetProductAttributesQuery(sinceId); - - return new ApiList(query, page - 1, limit); - } - - public int GetProductAttributesCount() - { - return GetProductAttributesQuery().Count(); - } - - ProductAttribute IProductAttributesApiService.GetById(int id) - { - if (id <= 0) - return null; - - return _productAttributesRepository.GetById(id); - } - - private IQueryable GetProductAttributesQuery(int sinceId = Configurations.DefaultSinceId) - { - var query = _productAttributesRepository.Table; - - if (sinceId > 0) - { - query = query.Where(productAttribute => productAttribute.Id > sinceId); - } - - query = query.OrderBy(productAttribute => productAttribute.Id); - - return query; - } - } +using Nop.Core.Domain.Catalog; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class ProductAttributesApiService : IProductAttributesApiService + { + private readonly IRepository _productAttributesRepository; + + public ProductAttributesApiService(IRepository productAttributesRepository) + { + _productAttributesRepository = productAttributesRepository; + } + + public IList GetProductAttributes(int limit = Configurations.DefaultLimit, + int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId) + { + var query = GetProductAttributesQuery(sinceId); + + return new ApiList(query, page - 1, limit); + } + + public int GetProductAttributesCount() + { + return GetProductAttributesQuery().Count(); + } + + ProductAttribute IProductAttributesApiService.GetById(int id) + { + if (id <= 0) + return null; + + return _productAttributesRepository.GetById(id); + } + + private IQueryable GetProductAttributesQuery(int sinceId = Configurations.DefaultSinceId) + { + var query = _productAttributesRepository.Table; + + if (sinceId > 0) + { + query = query.Where(productAttribute => productAttribute.Id > sinceId); + } + + query = query.OrderBy(productAttribute => productAttribute.Id); + + return query; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/ProductCategoryMappingsApiService.cs b/Services/ProductCategoryMappingsApiService.cs similarity index 91% rename from Nop.Plugin.Api/Services/ProductCategoryMappingsApiService.cs rename to Services/ProductCategoryMappingsApiService.cs index 1a950fb..e323052 100644 --- a/Nop.Plugin.Api/Services/ProductCategoryMappingsApiService.cs +++ b/Services/ProductCategoryMappingsApiService.cs @@ -1,66 +1,66 @@ -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; - -namespace Nop.Plugin.Api.Services -{ - public class ProductCategoryMappingsApiService : IProductCategoryMappingsApiService - { - private readonly IRepository _productCategoryMappingsRepository; - - public ProductCategoryMappingsApiService(IRepository productCategoryMappingsRepository) - { - _productCategoryMappingsRepository = productCategoryMappingsRepository; - } - - public IList GetMappings(int? productId = null, - int? categoryId = null, int limit = Configurations.DefaultLimit, - int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId) - { - var query = GetMappingsQuery(productId, categoryId, sinceId); - - return new ApiList(query, page - 1, limit); - } - - public int GetMappingsCount(int? productId = null, int? categoryId = null) - { - return GetMappingsQuery(productId, categoryId).Count(); - } - - public ProductCategory GetById(int id) - { - if (id <= 0) - return null; - - return _productCategoryMappingsRepository.GetById(id); - } - - private IQueryable GetMappingsQuery(int? productId = null, - int? categoryId = null, int sinceId = Configurations.DefaultSinceId) - { - var query = _productCategoryMappingsRepository.Table; - - if (productId != null) - { - query = query.Where(mapping => mapping.ProductId == productId); - } - - if (categoryId != null) - { - query = query.Where(mapping => mapping.CategoryId == categoryId); - } - - if (sinceId > 0) - { - query = query.Where(mapping => mapping.Id > sinceId); - } - - query = query.OrderBy(mapping => mapping.Id); - - return query; - } - } +using Nop.Core.Domain.Catalog; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class ProductCategoryMappingsApiService : IProductCategoryMappingsApiService + { + private readonly IRepository _productCategoryMappingsRepository; + + public ProductCategoryMappingsApiService(IRepository productCategoryMappingsRepository) + { + _productCategoryMappingsRepository = productCategoryMappingsRepository; + } + + public IList GetMappings(int? productId = null, + int? categoryId = null, int limit = Configurations.DefaultLimit, + int page = Configurations.DefaultPageValue, int sinceId = Configurations.DefaultSinceId) + { + var query = GetMappingsQuery(productId, categoryId, sinceId); + + return new ApiList(query, page - 1, limit); + } + + public int GetMappingsCount(int? productId = null, int? categoryId = null) + { + return GetMappingsQuery(productId, categoryId).Count(); + } + + public ProductCategory GetById(int id) + { + if (id <= 0) + return null; + + return _productCategoryMappingsRepository.GetById(id); + } + + private IQueryable GetMappingsQuery(int? productId = null, + int? categoryId = null, int sinceId = Configurations.DefaultSinceId) + { + var query = _productCategoryMappingsRepository.Table; + + if (productId != null) + { + query = query.Where(mapping => mapping.ProductId == productId); + } + + if (categoryId != null) + { + query = query.Where(mapping => mapping.CategoryId == categoryId); + } + + if (sinceId > 0) + { + query = query.Where(mapping => mapping.Id > sinceId); + } + + query = query.OrderBy(mapping => mapping.Id); + + return query; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/ProductManufacturerMappingsApiService.cs b/Services/ProductManufacturerMappingsApiService.cs similarity index 95% rename from Nop.Plugin.Api/Services/ProductManufacturerMappingsApiService.cs rename to Services/ProductManufacturerMappingsApiService.cs index 76f8c0d..608d7d1 100644 --- a/Nop.Plugin.Api/Services/ProductManufacturerMappingsApiService.cs +++ b/Services/ProductManufacturerMappingsApiService.cs @@ -1,9 +1,9 @@ -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using Nop.Core.Domain.Catalog; +using Nop.Data; using Nop.Plugin.Api.DataStructures; using System.Collections.Generic; using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/ProductPictureService.cs b/Services/ProductPictureService.cs similarity index 91% rename from Nop.Plugin.Api/Services/ProductPictureService.cs rename to Services/ProductPictureService.cs index 4c4aa8d..aafae1f 100644 --- a/Nop.Plugin.Api/Services/ProductPictureService.cs +++ b/Services/ProductPictureService.cs @@ -1,6 +1,6 @@ -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Catalog; +using Nop.Data; +using System.Linq; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/ShoppingCartItemApiService.cs b/Services/ShoppingCartItemApiService.cs similarity index 94% rename from Nop.Plugin.Api/Services/ShoppingCartItemApiService.cs rename to Services/ShoppingCartItemApiService.cs index ca341e2..218f3bc 100644 --- a/Nop.Plugin.Api/Services/ShoppingCartItemApiService.cs +++ b/Services/ShoppingCartItemApiService.cs @@ -1,77 +1,77 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Nop.Core.Data; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.Constants; -using Nop.Plugin.Api.DataStructures; -using Nop.Core; - -namespace Nop.Plugin.Api.Services -{ - public class ShoppingCartItemApiService : IShoppingCartItemApiService - { - private readonly IRepository _shoppingCartItemsRepository; - private readonly IStoreContext _storeContext; - - public ShoppingCartItemApiService(IRepository shoppingCartItemsRepository, IStoreContext storeContext) - { - _shoppingCartItemsRepository = shoppingCartItemsRepository; - _storeContext = storeContext; - } - - public List GetShoppingCartItems(int? customerId = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, - DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, int limit = Configurations.DefaultLimit, - int page = Configurations.DefaultPageValue) - { - var query = GetShoppingCartItemsQuery(customerId, createdAtMin, createdAtMax, - updatedAtMin, updatedAtMax); - - return new ApiList(query, page - 1, limit); - } - - public ShoppingCartItem GetShoppingCartItem(int id) - { - return _shoppingCartItemsRepository.GetById(id); - } - - private IQueryable GetShoppingCartItemsQuery(int? customerId = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, - DateTime? updatedAtMin = null, DateTime? updatedAtMax = null) - { - var query = _shoppingCartItemsRepository.Table; - - if (customerId != null) - { - query = query.Where(shoppingCartItem => shoppingCartItem.CustomerId == customerId); - } - - if (createdAtMin != null) - { - query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); - } - - if (createdAtMax != null) - { - query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); - } - - if (updatedAtMin != null) - { - query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); - } - - if (updatedAtMax != null) - { - query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); - } - - // items for the current store only - var currentStoreId = _storeContext.CurrentStore.Id; - query = query.Where(c => c.StoreId == currentStoreId); - - query = query.OrderBy(shoppingCartItem => shoppingCartItem.Id); - - return query; - } - } +using Nop.Core; +using Nop.Core.Domain.Orders; +using Nop.Data; +using Nop.Plugin.Api.DataStructures; +using System; +using System.Collections.Generic; +using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; + +namespace Nop.Plugin.Api.Services +{ + public class ShoppingCartItemApiService : IShoppingCartItemApiService + { + private readonly IRepository _shoppingCartItemsRepository; + private readonly IStoreContext _storeContext; + + public ShoppingCartItemApiService(IRepository shoppingCartItemsRepository, IStoreContext storeContext) + { + _shoppingCartItemsRepository = shoppingCartItemsRepository; + _storeContext = storeContext; + } + + public List GetShoppingCartItems(int? customerId = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, + DateTime? updatedAtMin = null, DateTime? updatedAtMax = null, int limit = Configurations.DefaultLimit, + int page = Configurations.DefaultPageValue) + { + var query = GetShoppingCartItemsQuery(customerId, createdAtMin, createdAtMax, + updatedAtMin, updatedAtMax); + + return new ApiList(query, page - 1, limit); + } + + public ShoppingCartItem GetShoppingCartItem(int id) + { + return _shoppingCartItemsRepository.GetById(id); + } + + private IQueryable GetShoppingCartItemsQuery(int? customerId = null, DateTime? createdAtMin = null, DateTime? createdAtMax = null, + DateTime? updatedAtMin = null, DateTime? updatedAtMax = null) + { + var query = _shoppingCartItemsRepository.Table; + + if (customerId != null) + { + query = query.Where(shoppingCartItem => shoppingCartItem.CustomerId == customerId); + } + + if (createdAtMin != null) + { + query = query.Where(c => c.CreatedOnUtc > createdAtMin.Value); + } + + if (createdAtMax != null) + { + query = query.Where(c => c.CreatedOnUtc < createdAtMax.Value); + } + + if (updatedAtMin != null) + { + query = query.Where(c => c.UpdatedOnUtc > updatedAtMin.Value); + } + + if (updatedAtMax != null) + { + query = query.Where(c => c.UpdatedOnUtc < updatedAtMax.Value); + } + + // items for the current store only + var currentStoreId = _storeContext.CurrentStore.Id; + query = query.Where(c => c.StoreId == currentStoreId); + + query = query.OrderBy(shoppingCartItem => shoppingCartItem.Id); + + return query; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Services/SpecificationAttributesApiService.cs b/Services/SpecificationAttributesApiService.cs similarity index 96% rename from Nop.Plugin.Api/Services/SpecificationAttributesApiService.cs rename to Services/SpecificationAttributesApiService.cs index 4ddecf0..e37b4b0 100644 --- a/Nop.Plugin.Api/Services/SpecificationAttributesApiService.cs +++ b/Services/SpecificationAttributesApiService.cs @@ -1,9 +1,9 @@ -using Nop.Core.Data; -using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.Constants; +using Nop.Core.Domain.Catalog; +using Nop.Data; using Nop.Plugin.Api.DataStructures; using System.Collections.Generic; using System.Linq; +using static Nop.Plugin.Api.Infrastructure.Constants; namespace Nop.Plugin.Api.Services { diff --git a/Nop.Plugin.Api/Services/WebHookService.cs b/Services/WebHookService.cs similarity index 97% rename from Nop.Plugin.Api/Services/WebHookService.cs rename to Services/WebHookService.cs index 72986e2..020ddff 100644 --- a/Nop.Plugin.Api/Services/WebHookService.cs +++ b/Services/WebHookService.cs @@ -1,81 +1,81 @@ -//using Nop.Plugin.Api.WebHooks; - -//namespace Nop.Plugin.Api.Services -//{ -// using Microsoft.AspNet.WebHooks; -// using Microsoft.AspNet.WebHooks.Diagnostics; -// using Microsoft.AspNet.WebHooks.Services; -// using Nop.Plugin.Api.Domain; -// using Nop.Plugin.Api.Helpers; -// using System; -// using System.Collections.Generic; -// using System.Web.Http.Tracing; - -// public class WebHookService : IWebHookService -// { -// private IWebHookManager _webHookManager; -// private IWebHookSender _webHookSender; -// private IWebHookStore _webHookStore; -// private IWebHookFilterManager _webHookFilterManager; -// private ILogger _logger; - -// private readonly IConfigManagerHelper _configManagerHelper; - -// public WebHookService(IConfigManagerHelper configManagerHelper,ILogger logger) -// { -// _configManagerHelper = configManagerHelper; -// _logger = logger; -// } - -// public IWebHookFilterManager GetWebHookFilterManager() -// { -// if (_webHookFilterManager == null) -// { -// var filterProviders = new List(); -// filterProviders.Add(new FilterProvider()); -// _webHookFilterManager = new WebHookFilterManager(filterProviders); -// } - -// return _webHookFilterManager; -// } - -// public IWebHookManager GetWebHookManager() -// { -// if (_webHookManager == null) -// { -// _webHookManager = new WebHookManager(GetWebHookStore(), GetWebHookSender(), _logger); -// } - -// return _webHookManager; -// } - -// public IWebHookSender GetWebHookSender() -// { -// if (_webHookSender == null) -// { -// _webHookSender = new ApiWebHookSender(_logger); -// } - -// return _webHookSender; -// } - -// public IWebHookStore GetWebHookStore() -// { -// if (_webHookStore == null) -// { -// var dataSettings = _configManagerHelper.DataSettings; -// Microsoft.AspNet.WebHooks.Config.SettingsDictionary settings = new Microsoft.AspNet.WebHooks.Config.SettingsDictionary(); -// settings.Add("MS_SqlStoreConnectionString", dataSettings.DataConnectionString); -// settings.Connections.Add("MS_SqlStoreConnectionString", new Microsoft.AspNet.WebHooks.Config.ConnectionSettings("MS_SqlStoreConnectionString", dataSettings.DataConnectionString)); - -// Microsoft.AspNet.WebHooks.IWebHookStore store = new Microsoft.AspNet.WebHooks.SqlWebHookStore(settings, _logger); - -// Microsoft.AspNet.WebHooks.Services.CustomServices.SetStore(store); - -// _webHookStore = CustomServices.GetStore(); -// } - -// return _webHookStore; -// } -// } -//} +//using Nop.Plugin.Api.WebHooks; + +//namespace Nop.Plugin.Api.Services +//{ +// using Microsoft.AspNet.WebHooks; +// using Microsoft.AspNet.WebHooks.Diagnostics; +// using Microsoft.AspNet.WebHooks.Services; +// using Nop.Plugin.Api.Domain; +// using Nop.Plugin.Api.Helpers; +// using System; +// using System.Collections.Generic; +// using System.Web.Http.Tracing; + +// public class WebHookService : IWebHookService +// { +// private IWebHookManager _webHookManager; +// private IWebHookSender _webHookSender; +// private IWebHookStore _webHookStore; +// private IWebHookFilterManager _webHookFilterManager; +// private ILogger _logger; + +// private readonly IConfigManagerHelper _configManagerHelper; + +// public WebHookService(IConfigManagerHelper configManagerHelper,ILogger logger) +// { +// _configManagerHelper = configManagerHelper; +// _logger = logger; +// } + +// public IWebHookFilterManager GetWebHookFilterManager() +// { +// if (_webHookFilterManager == null) +// { +// var filterProviders = new List(); +// filterProviders.Add(new FilterProvider()); +// _webHookFilterManager = new WebHookFilterManager(filterProviders); +// } + +// return _webHookFilterManager; +// } + +// public IWebHookManager GetWebHookManager() +// { +// if (_webHookManager == null) +// { +// _webHookManager = new WebHookManager(GetWebHookStore(), GetWebHookSender(), _logger); +// } + +// return _webHookManager; +// } + +// public IWebHookSender GetWebHookSender() +// { +// if (_webHookSender == null) +// { +// _webHookSender = new ApiWebHookSender(_logger); +// } + +// return _webHookSender; +// } + +// public IWebHookStore GetWebHookStore() +// { +// if (_webHookStore == null) +// { +// var dataSettings = _configManagerHelper.DataSettings; +// Microsoft.AspNet.WebHooks.Config.SettingsDictionary settings = new Microsoft.AspNet.WebHooks.Config.SettingsDictionary(); +// settings.Add("MS_SqlStoreConnectionString", dataSettings.DataConnectionString); +// settings.Connections.Add("MS_SqlStoreConnectionString", new Microsoft.AspNet.WebHooks.Config.ConnectionSettings("MS_SqlStoreConnectionString", dataSettings.DataConnectionString)); + +// Microsoft.AspNet.WebHooks.IWebHookStore store = new Microsoft.AspNet.WebHooks.SqlWebHookStore(settings, _logger); + +// Microsoft.AspNet.WebHooks.Services.CustomServices.SetStore(store); + +// _webHookStore = CustomServices.GetStore(); +// } + +// return _webHookStore; +// } +// } +//} diff --git a/Nop.Plugin.Api/Validators/AddressDtoValidator.cs b/Validators/AddressDtoValidator.cs similarity index 98% rename from Nop.Plugin.Api/Validators/AddressDtoValidator.cs rename to Validators/AddressDtoValidator.cs index 483f540..4c76b4f 100644 --- a/Nop.Plugin.Api/Validators/AddressDtoValidator.cs +++ b/Validators/AddressDtoValidator.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs; +using Nop.Plugin.Api.DTO; using Nop.Plugin.Api.Helpers; using System.Collections.Generic; diff --git a/Nop.Plugin.Api/Validators/BaseDtoValidator.cs b/Validators/BaseDtoValidator.cs similarity index 99% rename from Nop.Plugin.Api/Validators/BaseDtoValidator.cs rename to Validators/BaseDtoValidator.cs index a047f1d..5576cbe 100644 --- a/Nop.Plugin.Api/Validators/BaseDtoValidator.cs +++ b/Validators/BaseDtoValidator.cs @@ -2,7 +2,7 @@ using FluentValidation.Results; using FluentValidation.Validators; using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.Base; +using Nop.Plugin.Api.DTO.Base; using Nop.Plugin.Api.Helpers; using System; using System.Collections.Generic; diff --git a/Nop.Plugin.Api/Validators/CategoryDtoValidator.cs b/Validators/CategoryDtoValidator.cs similarity index 91% rename from Nop.Plugin.Api/Validators/CategoryDtoValidator.cs rename to Validators/CategoryDtoValidator.cs index c043760..9884ea3 100644 --- a/Nop.Plugin.Api/Validators/CategoryDtoValidator.cs +++ b/Validators/CategoryDtoValidator.cs @@ -1,30 +1,30 @@ -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.Categories; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Validators -{ - public class CategoryDtoValidator : BaseDtoValidator - { - - #region Constructors - - public CategoryDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetNameRule(); - } - - #endregion - - #region Private Methods - - private void SetNameRule() - { - SetNotNullOrEmptyCreateOrUpdateRule(c => c.Name, "invalid name", "name"); - } - - #endregion - - } +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.Categories; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class CategoryDtoValidator : BaseDtoValidator + { + + #region Constructors + + public CategoryDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetNameRule(); + } + + #endregion + + #region Private Methods + + private void SetNameRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(c => c.Name, "invalid name", "name"); + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/CustomerDtoValidator.cs b/Validators/CustomerDtoValidator.cs similarity index 96% rename from Nop.Plugin.Api/Validators/CustomerDtoValidator.cs rename to Validators/CustomerDtoValidator.cs index c3d475d..6c55662 100644 --- a/Nop.Plugin.Api/Validators/CustomerDtoValidator.cs +++ b/Validators/CustomerDtoValidator.cs @@ -1,171 +1,171 @@ -using FluentValidation; -using FluentValidation.Results; -using FluentValidation.Validators; -using Microsoft.AspNetCore.Http; -using Nop.Core.Domain.Customers; -using Nop.Plugin.Api.DTOs; -using Nop.Plugin.Api.DTOs.Customers; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; - -namespace Nop.Plugin.Api.Validators -{ - public class CustomerDtoValidator : BaseDtoValidator - { - - #region Private Fields - - private readonly ICustomerRolesHelper _customerRolesHelper; - - #endregion - - #region Constructors - - public CustomerDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary, ICustomerRolesHelper customerRolesHelper) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - _customerRolesHelper = customerRolesHelper; - - SetEmailRule(); - SetRolesRule(); - SetPasswordRule(); - - SetBillingAddressRule(); - SetShippingAddressRule(); - - SetCustomerAddressesRule(); - SetShoppingCartItemsRule(); - } - - #endregion - - #region Private Methods - - private void SetCustomerAddressesRule() - { - var key = "addresses"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleForEach(c => c.Addresses) - .Custom((addressDto, validationContext) => - { - var addressJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, addressDto); - - var validator = new AddressDtoValidator(HttpContextAccessor, JsonHelper, addressJsonDictionary); - - //force create validation for new addresses - if (addressDto.Id == 0) - { - validator.HttpMethod = HttpMethod.Post; - } - - var validationResult = validator.Validate(addressDto); - - MergeValidationResult(validationContext, validationResult); - }); - } - } - - private void SetBillingAddressRule() - { - var key = "billing_address"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleFor(c => c.BillingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); - } - } - - private void SetShippingAddressRule() - { - var key = "shipping_address"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleFor(c => c.ShippingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); - } - } - - private void SetEmailRule() - { - SetNotNullOrEmptyCreateOrUpdateRule(c => c.Email, "invalid email", "email"); - } - - private void SetPasswordRule() - { - SetNotNullOrEmptyCreateOrUpdateRule(c => c.Password, "invalid password", "password"); - } - - private void SetRolesRule() - { - if (HttpMethod == HttpMethod.Post || RequestJsonDictionary.ContainsKey("role_ids")) - { - IList customerRoles = null; - - RuleFor(x => x.RoleIds) - .NotNull() - .Must(roles => roles.Count > 0) - .WithMessage("role_ids required") - .DependentRules(() => RuleFor(dto => dto.RoleIds) - .Must(roleIds => - { - if (customerRoles == null) - { - customerRoles = _customerRolesHelper.GetValidCustomerRoles(roleIds); - } - - var isInGuestAndRegisterRoles = _customerRolesHelper.IsInGuestsRole(customerRoles) && - _customerRolesHelper.IsInRegisteredRole(customerRoles); - - // Customer can not be in guest and register roles simultaneously - return !isInGuestAndRegisterRoles; - }) - .WithMessage("must not be in guest and register roles simultaneously") - .DependentRules(() => RuleFor(dto => dto.RoleIds) - .Must(roleIds => - { - if (customerRoles == null) - { - customerRoles = _customerRolesHelper.GetValidCustomerRoles(roleIds); - } - - var isInGuestOrRegisterRoles = _customerRolesHelper.IsInGuestsRole(customerRoles) || - _customerRolesHelper.IsInRegisteredRole(customerRoles); - - // Customer must be in either guest or register role. - return isInGuestOrRegisterRoles; - }) - .WithMessage("must be in guest or register role") - ) - ); - } - } - - private void SetShoppingCartItemsRule() - { - var key = "shopping_cart_items"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleForEach(c => c.ShoppingCartItems) - .Custom((shoppingCartItemDto, validationContext) => - { - var shoppingCartItemJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, shoppingCartItemDto); - - var validator = new ShoppingCartItemDtoValidator(HttpContextAccessor, JsonHelper, shoppingCartItemJsonDictionary); - - //force create validation for new addresses - if (shoppingCartItemDto.Id == 0) - { - validator.HttpMethod = HttpMethod.Post; - } - - var validationResult = validator.Validate(shoppingCartItemDto); - - MergeValidationResult(validationContext, validationResult); - }); - } - } - - #endregion - - } +using FluentValidation; +using FluentValidation.Results; +using FluentValidation.Validators; +using Microsoft.AspNetCore.Http; +using Nop.Core.Domain.Customers; +using Nop.Plugin.Api.DTO; +using Nop.Plugin.Api.DTO.Customers; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; + +namespace Nop.Plugin.Api.Validators +{ + public class CustomerDtoValidator : BaseDtoValidator + { + + #region Private Fields + + private readonly ICustomerRolesHelper _customerRolesHelper; + + #endregion + + #region Constructors + + public CustomerDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary, ICustomerRolesHelper customerRolesHelper) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + _customerRolesHelper = customerRolesHelper; + + SetEmailRule(); + SetRolesRule(); + SetPasswordRule(); + + SetBillingAddressRule(); + SetShippingAddressRule(); + + SetCustomerAddressesRule(); + SetShoppingCartItemsRule(); + } + + #endregion + + #region Private Methods + + private void SetCustomerAddressesRule() + { + var key = "addresses"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleForEach(c => c.Addresses) + .Custom((addressDto, validationContext) => + { + var addressJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, addressDto); + + var validator = new AddressDtoValidator(HttpContextAccessor, JsonHelper, addressJsonDictionary); + + //force create validation for new addresses + if (addressDto.Id == 0) + { + validator.HttpMethod = HttpMethod.Post; + } + + var validationResult = validator.Validate(addressDto); + + MergeValidationResult(validationContext, validationResult); + }); + } + } + + private void SetBillingAddressRule() + { + var key = "billing_address"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleFor(c => c.BillingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); + } + } + + private void SetShippingAddressRule() + { + var key = "shipping_address"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleFor(c => c.ShippingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); + } + } + + private void SetEmailRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(c => c.Email, "invalid email", "email"); + } + + private void SetPasswordRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(c => c.Password, "invalid password", "password"); + } + + private void SetRolesRule() + { + if (HttpMethod == HttpMethod.Post || RequestJsonDictionary.ContainsKey("role_ids")) + { + IList customerRoles = null; + + RuleFor(x => x.RoleIds) + .NotNull() + .Must(roles => roles.Count > 0) + .WithMessage("role_ids required") + .DependentRules(() => RuleFor(dto => dto.RoleIds) + .Must(roleIds => + { + if (customerRoles == null) + { + customerRoles = _customerRolesHelper.GetValidCustomerRoles(roleIds); + } + + var isInGuestAndRegisterRoles = _customerRolesHelper.IsInGuestsRole(customerRoles) && + _customerRolesHelper.IsInRegisteredRole(customerRoles); + + // Customer can not be in guest and register roles simultaneously + return !isInGuestAndRegisterRoles; + }) + .WithMessage("must not be in guest and register roles simultaneously") + .DependentRules(() => RuleFor(dto => dto.RoleIds) + .Must(roleIds => + { + if (customerRoles == null) + { + customerRoles = _customerRolesHelper.GetValidCustomerRoles(roleIds); + } + + var isInGuestOrRegisterRoles = _customerRolesHelper.IsInGuestsRole(customerRoles) || + _customerRolesHelper.IsInRegisteredRole(customerRoles); + + // Customer must be in either guest or register role. + return isInGuestOrRegisterRoles; + }) + .WithMessage("must be in guest or register role") + ) + ); + } + } + + private void SetShoppingCartItemsRule() + { + var key = "shopping_cart_items"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleForEach(c => c.ShoppingCartItems) + .Custom((shoppingCartItemDto, validationContext) => + { + var shoppingCartItemJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, shoppingCartItemDto); + + var validator = new ShoppingCartItemDtoValidator(HttpContextAccessor, JsonHelper, shoppingCartItemJsonDictionary); + + //force create validation for new addresses + if (shoppingCartItemDto.Id == 0) + { + validator.HttpMethod = HttpMethod.Post; + } + + var validationResult = validator.Validate(shoppingCartItemDto); + + MergeValidationResult(validationContext, validationResult); + }); + } + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/FieldsValidator.cs b/Validators/FieldsValidator.cs similarity index 97% rename from Nop.Plugin.Api/Validators/FieldsValidator.cs rename to Validators/FieldsValidator.cs index ce477cc..bedfe3f 100644 --- a/Nop.Plugin.Api/Validators/FieldsValidator.cs +++ b/Validators/FieldsValidator.cs @@ -1,45 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace Nop.Plugin.Api.Validators -{ - public class FieldsValidator : IFieldsValidator - { - private static IEnumerable GetPropertiesIntoList(string fields) - { - var properties = fields.ToLowerInvariant() - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(x => x.Trim()) - .Distinct() - .ToList(); - - return properties; - } - - public Dictionary GetValidFields(string fields, Type type) - { - // This check ensures that the fields won't be null, because it can couse exception. - fields = fields ?? string.Empty; - // This is needed in case you pass the fields as you see them in the json representation of the objects. - // By specification if the property consists of several words, each word should be separetate from the others with underscore. - fields = fields.Replace("_", string.Empty); - - var validFields = new Dictionary(); - var fieldsAsList = GetPropertiesIntoList(fields); - - foreach (var field in fieldsAsList) - { - var propertyExists = type.GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null; - - if (propertyExists) - { - validFields.Add(field, true); - } - } - - return validFields; - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Nop.Plugin.Api.Validators +{ + public class FieldsValidator : IFieldsValidator + { + private static IEnumerable GetPropertiesIntoList(string fields) + { + var properties = fields.ToLowerInvariant() + .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Trim()) + .Distinct() + .ToList(); + + return properties; + } + + public Dictionary GetValidFields(string fields, Type type) + { + // This check ensures that the fields won't be null, because it can couse exception. + fields = fields ?? string.Empty; + // This is needed in case you pass the fields as you see them in the json representation of the objects. + // By specification if the property consists of several words, each word should be separetate from the others with underscore. + fields = fields.Replace("_", string.Empty); + + var validFields = new Dictionary(); + var fieldsAsList = GetPropertiesIntoList(fields); + + foreach (var field in fieldsAsList) + { + var propertyExists = type.GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null; + + if (propertyExists) + { + validFields.Add(field, true); + } + } + + return validFields; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/IFieldsValidator.cs b/Validators/IFieldsValidator.cs similarity index 100% rename from Nop.Plugin.Api/Validators/IFieldsValidator.cs rename to Validators/IFieldsValidator.cs diff --git a/Nop.Plugin.Api/Validators/ManufacturerDtoValidator.cs b/Validators/ManufacturerDtoValidator.cs similarity index 94% rename from Nop.Plugin.Api/Validators/ManufacturerDtoValidator.cs rename to Validators/ManufacturerDtoValidator.cs index 6717dab..8370129 100644 --- a/Nop.Plugin.Api/Validators/ManufacturerDtoValidator.cs +++ b/Validators/ManufacturerDtoValidator.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Http; using Nop.Plugin.Api.Helpers; using System.Collections.Generic; -using Nop.Plugin.Api.DTOs.Manufacturers; +using Nop.Plugin.Api.DTO.Manufacturers; namespace Nop.Plugin.Api.Validators { diff --git a/Nop.Plugin.Api/Validators/OrderDtoValidator.cs b/Validators/OrderDtoValidator.cs similarity index 95% rename from Nop.Plugin.Api/Validators/OrderDtoValidator.cs rename to Validators/OrderDtoValidator.cs index 5d7d6cb..f4de4f5 100644 --- a/Nop.Plugin.Api/Validators/OrderDtoValidator.cs +++ b/Validators/OrderDtoValidator.cs @@ -1,78 +1,78 @@ -using FluentValidation; -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.Orders; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; -using System.Net.Http; - -namespace Nop.Plugin.Api.Validators -{ - public class OrderDtoValidator : BaseDtoValidator - { - - #region Constructors - - public OrderDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetCustomerIdRule(); - SetOrderItemsRule(); - - SetBillingAddressRule(); - SetShippingAddressRule(); - } - - #endregion - - #region Private Methods - - private void SetBillingAddressRule() - { - var key = "billing_address"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleFor(o => o.BillingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); - } - } - - private void SetShippingAddressRule() - { - var key = "shipping_address"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleFor(o => o.ShippingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); - } - } - - private void SetCustomerIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(o => o.CustomerId, "invalid customer_id", "customer_id"); - } - - private void SetOrderItemsRule() - { - var key = "order_items"; - if (RequestJsonDictionary.ContainsKey(key)) - { - RuleForEach(c => c.OrderItems) - .Custom((orderItemDto, validationContext) => - { - var orderItemJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, orderItemDto); - - var validator = new OrderItemDtoValidator(HttpContextAccessor, JsonHelper, orderItemJsonDictionary); - - //force create validation for new addresses - if (orderItemDto.Id == 0) - { - validator.HttpMethod = HttpMethod.Post; - } - - var validationResult = validator.Validate(orderItemDto); - MergeValidationResult(validationContext, validationResult); - }); - } - } - - #endregion - - } +using FluentValidation; +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.Orders; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; +using System.Net.Http; + +namespace Nop.Plugin.Api.Validators +{ + public class OrderDtoValidator : BaseDtoValidator + { + + #region Constructors + + public OrderDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetCustomerIdRule(); + SetOrderItemsRule(); + + SetBillingAddressRule(); + SetShippingAddressRule(); + } + + #endregion + + #region Private Methods + + private void SetBillingAddressRule() + { + var key = "billing_address"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleFor(o => o.BillingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); + } + } + + private void SetShippingAddressRule() + { + var key = "shipping_address"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleFor(o => o.ShippingAddress).SetValidator(new AddressDtoValidator(HttpContextAccessor, JsonHelper, (Dictionary)RequestJsonDictionary[key])); + } + } + + private void SetCustomerIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(o => o.CustomerId, "invalid customer_id", "customer_id"); + } + + private void SetOrderItemsRule() + { + var key = "order_items"; + if (RequestJsonDictionary.ContainsKey(key)) + { + RuleForEach(c => c.OrderItems) + .Custom((orderItemDto, validationContext) => + { + var orderItemJsonDictionary = GetRequestJsonDictionaryCollectionItemDictionary(key, orderItemDto); + + var validator = new OrderItemDtoValidator(HttpContextAccessor, JsonHelper, orderItemJsonDictionary); + + //force create validation for new addresses + if (orderItemDto.Id == 0) + { + validator.HttpMethod = HttpMethod.Post; + } + + var validationResult = validator.Validate(orderItemDto); + MergeValidationResult(validationContext, validationResult); + }); + } + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/OrderItemDtoValidator.cs b/Validators/OrderItemDtoValidator.cs similarity index 92% rename from Nop.Plugin.Api/Validators/OrderItemDtoValidator.cs rename to Validators/OrderItemDtoValidator.cs index 886ec32..f0d5632 100644 --- a/Nop.Plugin.Api/Validators/OrderItemDtoValidator.cs +++ b/Validators/OrderItemDtoValidator.cs @@ -1,36 +1,36 @@ -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.OrderItems; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Validators -{ - public class OrderItemDtoValidator : BaseDtoValidator - { - - #region Constructors - - public OrderItemDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetProductIdRule(); - SetQuantityRule(); - } - - #endregion - - #region Private Methods - - private void SetProductIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(o => o.ProductId, "invalid product_id", "product_id"); - } - - private void SetQuantityRule() - { - SetGreaterThanZeroCreateOrUpdateRule(o => o.Quantity, "invalid quanitty", "quantity"); - } - - #endregion - - } +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.OrderItems; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class OrderItemDtoValidator : BaseDtoValidator + { + + #region Constructors + + public OrderItemDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetProductIdRule(); + SetQuantityRule(); + } + + #endregion + + #region Private Methods + + private void SetProductIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(o => o.ProductId, "invalid product_id", "product_id"); + } + + private void SetQuantityRule() + { + SetGreaterThanZeroCreateOrUpdateRule(o => o.Quantity, "invalid quanitty", "quantity"); + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/ProductAttributeCombinationDtoValidator.cs b/Validators/ProductAttributeCombinationDtoValidator.cs similarity index 96% rename from Nop.Plugin.Api/Validators/ProductAttributeCombinationDtoValidator.cs rename to Validators/ProductAttributeCombinationDtoValidator.cs index 2b8b643..dd39202 100644 --- a/Nop.Plugin.Api/Validators/ProductAttributeCombinationDtoValidator.cs +++ b/Validators/ProductAttributeCombinationDtoValidator.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.Products; +using Nop.Plugin.Api.DTO.Products; using Nop.Plugin.Api.Helpers; using System.Collections.Generic; diff --git a/Nop.Plugin.Api/Validators/ProductAttributeDtoValidator.cs b/Validators/ProductAttributeDtoValidator.cs similarity index 91% rename from Nop.Plugin.Api/Validators/ProductAttributeDtoValidator.cs rename to Validators/ProductAttributeDtoValidator.cs index db0f379..5bee86b 100644 --- a/Nop.Plugin.Api/Validators/ProductAttributeDtoValidator.cs +++ b/Validators/ProductAttributeDtoValidator.cs @@ -1,30 +1,30 @@ -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.ProductAttributes; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Validators -{ - public class ProductAttributeDtoValidator : BaseDtoValidator - { - - #region Constructors - - public ProductAttributeDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetNameRule(); - } - - #endregion - - #region Private Methods - - private void SetNameRule() - { - SetNotNullOrEmptyCreateOrUpdateRule(p => p.Name, "invalid name", "name"); - } - - #endregion - - } +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.ProductAttributes; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class ProductAttributeDtoValidator : BaseDtoValidator + { + + #region Constructors + + public ProductAttributeDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetNameRule(); + } + + #endregion + + #region Private Methods + + private void SetNameRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(p => p.Name, "invalid name", "name"); + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/ProductCategoryMappingDtoValidator.cs b/Validators/ProductCategoryMappingDtoValidator.cs similarity index 92% rename from Nop.Plugin.Api/Validators/ProductCategoryMappingDtoValidator.cs rename to Validators/ProductCategoryMappingDtoValidator.cs index d6c4ede..e9a80a1 100644 --- a/Nop.Plugin.Api/Validators/ProductCategoryMappingDtoValidator.cs +++ b/Validators/ProductCategoryMappingDtoValidator.cs @@ -1,36 +1,36 @@ -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.ProductCategoryMappings; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Validators -{ - public class ProductCategoryMappingDtoValidator : BaseDtoValidator - { - - #region Constructors - - public ProductCategoryMappingDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetCategoryIdRule(); - SetProductIdRule(); - } - - #endregion - - #region Private Methods - - private void SetCategoryIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(p => p.CategoryId, "invalid category_id", "category_id"); - } - - private void SetProductIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(p => p.ProductId, "invalid product_id", "product_id"); - } - - #endregion - - } +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.ProductCategoryMappings; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class ProductCategoryMappingDtoValidator : BaseDtoValidator + { + + #region Constructors + + public ProductCategoryMappingDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetCategoryIdRule(); + SetProductIdRule(); + } + + #endregion + + #region Private Methods + + private void SetCategoryIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(p => p.CategoryId, "invalid category_id", "category_id"); + } + + private void SetProductIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(p => p.ProductId, "invalid product_id", "product_id"); + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/ProductDtoValidator.cs b/Validators/ProductDtoValidator.cs similarity index 91% rename from Nop.Plugin.Api/Validators/ProductDtoValidator.cs rename to Validators/ProductDtoValidator.cs index 673e3ba..5c739d9 100644 --- a/Nop.Plugin.Api/Validators/ProductDtoValidator.cs +++ b/Validators/ProductDtoValidator.cs @@ -1,30 +1,30 @@ -using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.Products; -using Nop.Plugin.Api.Helpers; -using System.Collections.Generic; - -namespace Nop.Plugin.Api.Validators -{ - public class ProductDtoValidator : BaseDtoValidator - { - - #region Constructors - - public ProductDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetNameRule(); - } - - #endregion - - #region Private Methods - - private void SetNameRule() - { - SetNotNullOrEmptyCreateOrUpdateRule(p => p.Name, "invalid name", "name"); - } - - #endregion - - } +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class ProductDtoValidator : BaseDtoValidator + { + + #region Constructors + + public ProductDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetNameRule(); + } + + #endregion + + #region Private Methods + + private void SetNameRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(p => p.Name, "invalid name", "name"); + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/ProductManufacturerMappingDtoValidator.cs b/Validators/ProductManufacturerMappingDtoValidator.cs similarity index 94% rename from Nop.Plugin.Api/Validators/ProductManufacturerMappingDtoValidator.cs rename to Validators/ProductManufacturerMappingDtoValidator.cs index 177df5d..89fb67d 100644 --- a/Nop.Plugin.Api/Validators/ProductManufacturerMappingDtoValidator.cs +++ b/Validators/ProductManufacturerMappingDtoValidator.cs @@ -1,6 +1,6 @@  using Microsoft.AspNetCore.Http; -using Nop.Plugin.Api.DTOs.ProductManufacturerMappings; +using Nop.Plugin.Api.DTO.ProductManufacturerMappings; using Nop.Plugin.Api.Helpers; using System.Collections.Generic; diff --git a/Nop.Plugin.Api/Validators/ProductSpecificationAttributeDtoValidator.cs b/Validators/ProductSpecificationAttributeDtoValidator.cs similarity index 98% rename from Nop.Plugin.Api/Validators/ProductSpecificationAttributeDtoValidator.cs rename to Validators/ProductSpecificationAttributeDtoValidator.cs index d1bf8dd..c6b885a 100644 --- a/Nop.Plugin.Api/Validators/ProductSpecificationAttributeDtoValidator.cs +++ b/Validators/ProductSpecificationAttributeDtoValidator.cs @@ -1,6 +1,6 @@ using FluentValidation; using Nop.Core.Domain.Catalog; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.SpecificationAttributes; using System; using System.Collections.Generic; using System.Linq; diff --git a/Nop.Plugin.Api/Validators/ShoppingCartItemDtoValidator.cs b/Validators/ShoppingCartItemDtoValidator.cs similarity index 95% rename from Nop.Plugin.Api/Validators/ShoppingCartItemDtoValidator.cs rename to Validators/ShoppingCartItemDtoValidator.cs index 69c5d3e..c0f027c 100644 --- a/Nop.Plugin.Api/Validators/ShoppingCartItemDtoValidator.cs +++ b/Validators/ShoppingCartItemDtoValidator.cs @@ -1,90 +1,90 @@ -using FluentValidation; -using Microsoft.AspNetCore.Http; -using Nop.Core.Domain.Orders; -using Nop.Plugin.Api.DTOs.ShoppingCarts; -using Nop.Plugin.Api.Helpers; -using System; -using System.Collections.Generic; -using System.Net.Http; - -namespace Nop.Plugin.Api.Validators -{ - public class ShoppingCartItemDtoValidator : BaseDtoValidator - { - - #region Constructors - - public ShoppingCartItemDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) - { - SetCustomerIdRule(); - SetProductIdRule(); - SetQuantityRule(); - SetShoppingCartTypeRule(); - - SetRentalDateRules(); - } - - #endregion - - #region Private Methods - - private void SetCustomerIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(x => x.CustomerId, "invalid customer_id", "customer_id"); - } - - private void SetProductIdRule() - { - SetGreaterThanZeroCreateOrUpdateRule(x => x.ProductId, "invalid product_id", "product_id"); - } - - private void SetQuantityRule() - { - SetGreaterThanZeroCreateOrUpdateRule(x => x.Quantity, "invalid quantity", "quantity"); - } - - private void SetRentalDateRules() - { - if (RequestJsonDictionary.ContainsKey("rental_start_date_utc") || RequestJsonDictionary.ContainsKey("rental_end_date_utc")) - { - RuleFor(x => x.RentalStartDateUtc) - .NotNull() - .WithMessage("Please provide a rental start date"); - - RuleFor(x => x.RentalEndDateUtc) - .NotNull() - .WithMessage("Please provide a rental end date"); - - RuleFor(dto => dto) - .Must(dto => dto.RentalStartDateUtc < dto.RentalEndDateUtc) - .WithMessage("Rental start date should be before rental end date"); - - RuleFor(dto => dto) - .Must(dto => dto.RentalStartDateUtc > dto.CreatedOnUtc) - .WithMessage("Rental start date should be the future date"); - - RuleFor(dto => dto) - .Must(dto => dto.RentalEndDateUtc > dto.CreatedOnUtc) - .WithMessage("Rental end date should be the future date"); - } - } - - private void SetShoppingCartTypeRule() - { - if (HttpMethod == HttpMethod.Post || RequestJsonDictionary.ContainsKey("shopping_cart_type")) - { - RuleFor(x => x.ShoppingCartType) - .NotNull() - .Must(x => - { - var parsed = Enum.TryParse(x, true, out ShoppingCartType _); - return parsed; - }) - .WithMessage("Please provide a valid shopping cart type"); - } - } - - #endregion - - } +using FluentValidation; +using Microsoft.AspNetCore.Http; +using Nop.Core.Domain.Orders; +using Nop.Plugin.Api.DTO.ShoppingCarts; +using Nop.Plugin.Api.Helpers; +using System; +using System.Collections.Generic; +using System.Net.Http; + +namespace Nop.Plugin.Api.Validators +{ + public class ShoppingCartItemDtoValidator : BaseDtoValidator + { + + #region Constructors + + public ShoppingCartItemDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetCustomerIdRule(); + SetProductIdRule(); + SetQuantityRule(); + SetShoppingCartTypeRule(); + + SetRentalDateRules(); + } + + #endregion + + #region Private Methods + + private void SetCustomerIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(x => x.CustomerId, "invalid customer_id", "customer_id"); + } + + private void SetProductIdRule() + { + SetGreaterThanZeroCreateOrUpdateRule(x => x.ProductId, "invalid product_id", "product_id"); + } + + private void SetQuantityRule() + { + SetGreaterThanZeroCreateOrUpdateRule(x => x.Quantity, "invalid quantity", "quantity"); + } + + private void SetRentalDateRules() + { + if (RequestJsonDictionary.ContainsKey("rental_start_date_utc") || RequestJsonDictionary.ContainsKey("rental_end_date_utc")) + { + RuleFor(x => x.RentalStartDateUtc) + .NotNull() + .WithMessage("Please provide a rental start date"); + + RuleFor(x => x.RentalEndDateUtc) + .NotNull() + .WithMessage("Please provide a rental end date"); + + RuleFor(dto => dto) + .Must(dto => dto.RentalStartDateUtc < dto.RentalEndDateUtc) + .WithMessage("Rental start date should be before rental end date"); + + RuleFor(dto => dto) + .Must(dto => dto.RentalStartDateUtc > dto.CreatedOnUtc) + .WithMessage("Rental start date should be the future date"); + + RuleFor(dto => dto) + .Must(dto => dto.RentalEndDateUtc > dto.CreatedOnUtc) + .WithMessage("Rental end date should be the future date"); + } + } + + private void SetShoppingCartTypeRule() + { + if (HttpMethod == HttpMethod.Post || RequestJsonDictionary.ContainsKey("shopping_cart_type")) + { + RuleFor(x => x.ShoppingCartType) + .NotNull() + .Must(x => + { + var parsed = Enum.TryParse(x, true, out ShoppingCartType _); + return parsed; + }) + .WithMessage("Please provide a valid shopping cart type"); + } + } + + #endregion + + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/Validators/SpecificationAttributeDtoValidator.cs b/Validators/SpecificationAttributeDtoValidator.cs similarity index 95% rename from Nop.Plugin.Api/Validators/SpecificationAttributeDtoValidator.cs rename to Validators/SpecificationAttributeDtoValidator.cs index 054dd98..4dcf5da 100644 --- a/Nop.Plugin.Api/Validators/SpecificationAttributeDtoValidator.cs +++ b/Validators/SpecificationAttributeDtoValidator.cs @@ -1,5 +1,5 @@ using FluentValidation; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.SpecificationAttributes; using System; using System.Collections.Generic; diff --git a/Nop.Plugin.Api/Validators/SpecificationAttributeOptionDtoValidator.cs b/Validators/SpecificationAttributeOptionDtoValidator.cs similarity index 97% rename from Nop.Plugin.Api/Validators/SpecificationAttributeOptionDtoValidator.cs rename to Validators/SpecificationAttributeOptionDtoValidator.cs index a57cefa..7ee4482 100644 --- a/Nop.Plugin.Api/Validators/SpecificationAttributeOptionDtoValidator.cs +++ b/Validators/SpecificationAttributeOptionDtoValidator.cs @@ -1,5 +1,5 @@ using FluentValidation; -using Nop.Plugin.Api.DTOs.SpecificationAttributes; +using Nop.Plugin.Api.DTO.SpecificationAttributes; using System; using System.Collections.Generic; diff --git a/Validators/TaxCategoryDtoValidator.cs b/Validators/TaxCategoryDtoValidator.cs new file mode 100644 index 0000000..d5827bf --- /dev/null +++ b/Validators/TaxCategoryDtoValidator.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Http; +using Nop.Plugin.Api.DTO.Products; +using Nop.Plugin.Api.DTO.TaxCategory; +using Nop.Plugin.Api.Helpers; +using System.Collections.Generic; + +namespace Nop.Plugin.Api.Validators +{ + public class TaxCategoryDtoValidator : BaseDtoValidator + { + #region Constructors + + public TaxCategoryDtoValidator(IHttpContextAccessor httpContextAccessor, IJsonHelper jsonHelper, Dictionary requestJsonDictionary) : base(httpContextAccessor, jsonHelper, requestJsonDictionary) + { + SetNameRule(); + } + + #endregion + + #region Private Methods + + private void SetNameRule() + { + SetNotNullOrEmptyCreateOrUpdateRule(p => p.Name, "invalid name", "name"); + } + + #endregion + } +} diff --git a/Nop.Plugin.Api/Validators/TypeValidator.cs b/Validators/TypeValidator.cs similarity index 97% rename from Nop.Plugin.Api/Validators/TypeValidator.cs rename to Validators/TypeValidator.cs index 74463ad..e07e288 100644 --- a/Nop.Plugin.Api/Validators/TypeValidator.cs +++ b/Validators/TypeValidator.cs @@ -1,122 +1,122 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; -using Newtonsoft.Json; -using Nop.Plugin.Api.Helpers; - -namespace Nop.Plugin.Api.Validators -{ - public class TypeValidator - { - public List InvalidProperties { get; set; } - - public TypeValidator() - { - InvalidProperties = new List(); - } - - public bool IsValid(Dictionary propertyValuePaires) - { - var isValid = true; - - var jsonPropertyNameTypePair = new Dictionary(); - - var objectProperties = typeof(T).GetProperties(); - - foreach (var property in objectProperties) - { - if (property.GetCustomAttribute(typeof(JsonPropertyAttribute)) is JsonPropertyAttribute jsonPropertyAttribute) - { - if (!jsonPropertyNameTypePair.ContainsKey(jsonPropertyAttribute.PropertyName)) - { - jsonPropertyNameTypePair.Add(jsonPropertyAttribute.PropertyName, property.PropertyType); - } - } - } - - foreach (var pair in propertyValuePaires) - { - var isCurrentPropertyValid = true; - - if (jsonPropertyNameTypePair.ContainsKey(pair.Key)) - { - var propertyType = jsonPropertyNameTypePair[pair.Key]; - - // handle nested properties - if (pair.Value is Dictionary objects) - { - isCurrentPropertyValid = ValidateNestedProperty(propertyType, objects); - } - // This case hadles collections. - else if (pair.Value is ICollection propertyValueAsCollection && propertyType.GetInterface("IEnumerable") != null) - { - var elementsType = ReflectionHelper.GetGenericElementType(propertyType); - - // Validate the collection items. - foreach (var item in propertyValueAsCollection) - { - isCurrentPropertyValid = IsCurrentPropertyValid(elementsType, item); - - if (!isCurrentPropertyValid) break; - } - } - else - { - isCurrentPropertyValid = IsCurrentPropertyValid(jsonPropertyNameTypePair[pair.Key], pair.Value); - } - - if (!isCurrentPropertyValid) - { - isValid = false; - InvalidProperties.Add(pair.Key); - } - } - } - - return isValid; - } - - private static bool ValidateNestedProperty(Type propertyType, Dictionary value) - { - var constructedType = typeof(TypeValidator<>).MakeGenericType(propertyType); - var typeValidatorForNestedProperty = Activator.CreateInstance(constructedType); - - var isValidMethod = constructedType.GetMethod("IsValid"); - - var isCurrentPropertyValid = (bool)isValidMethod.Invoke(typeValidatorForNestedProperty, new object[] { value }); - - return isCurrentPropertyValid; - } - - private static bool IsCurrentPropertyValid(Type type, object value) - { - var isCurrentPropertyValid = true; - - if (type.Namespace == "System") - { - var converter = TypeDescriptor.GetConverter(type); - - var valueToValidate = value; - - // This is needed because the isValid method does not work well if the value it is trying to validate is object. - if (value != null) - { - valueToValidate = string.Format(CultureInfo.InvariantCulture, "{0}", value); - } - - if (!converter.IsValid(valueToValidate)) isCurrentPropertyValid = false; - } - else - { - if (value != null) - { - isCurrentPropertyValid = ValidateNestedProperty(type, (Dictionary)value); - } - } - - return isCurrentPropertyValid; - } - } +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; +using Newtonsoft.Json; +using Nop.Plugin.Api.Helpers; + +namespace Nop.Plugin.Api.Validators +{ + public class TypeValidator + { + public List InvalidProperties { get; set; } + + public TypeValidator() + { + InvalidProperties = new List(); + } + + public bool IsValid(Dictionary propertyValuePaires) + { + var isValid = true; + + var jsonPropertyNameTypePair = new Dictionary(); + + var objectProperties = typeof(T).GetProperties(); + + foreach (var property in objectProperties) + { + if (property.GetCustomAttribute(typeof(JsonPropertyAttribute)) is JsonPropertyAttribute jsonPropertyAttribute) + { + if (!jsonPropertyNameTypePair.ContainsKey(jsonPropertyAttribute.PropertyName)) + { + jsonPropertyNameTypePair.Add(jsonPropertyAttribute.PropertyName, property.PropertyType); + } + } + } + + foreach (var pair in propertyValuePaires) + { + var isCurrentPropertyValid = true; + + if (jsonPropertyNameTypePair.ContainsKey(pair.Key)) + { + var propertyType = jsonPropertyNameTypePair[pair.Key]; + + // handle nested properties + if (pair.Value is Dictionary objects) + { + isCurrentPropertyValid = ValidateNestedProperty(propertyType, objects); + } + // This case hadles collections. + else if (pair.Value is ICollection propertyValueAsCollection && propertyType.GetInterface("IEnumerable") != null) + { + var elementsType = ReflectionHelper.GetGenericElementType(propertyType); + + // Validate the collection items. + foreach (var item in propertyValueAsCollection) + { + isCurrentPropertyValid = IsCurrentPropertyValid(elementsType, item); + + if (!isCurrentPropertyValid) break; + } + } + else + { + isCurrentPropertyValid = IsCurrentPropertyValid(jsonPropertyNameTypePair[pair.Key], pair.Value); + } + + if (!isCurrentPropertyValid) + { + isValid = false; + InvalidProperties.Add(pair.Key); + } + } + } + + return isValid; + } + + private static bool ValidateNestedProperty(Type propertyType, Dictionary value) + { + var constructedType = typeof(TypeValidator<>).MakeGenericType(propertyType); + var typeValidatorForNestedProperty = Activator.CreateInstance(constructedType); + + var isValidMethod = constructedType.GetMethod("IsValid"); + + var isCurrentPropertyValid = (bool)isValidMethod.Invoke(typeValidatorForNestedProperty, new object[] { value }); + + return isCurrentPropertyValid; + } + + private static bool IsCurrentPropertyValid(Type type, object value) + { + var isCurrentPropertyValid = true; + + if (type.Namespace == "System") + { + var converter = TypeDescriptor.GetConverter(type); + + var valueToValidate = value; + + // This is needed because the isValid method does not work well if the value it is trying to validate is object. + if (value != null) + { + valueToValidate = string.Format(CultureInfo.InvariantCulture, "{0}", value); + } + + if (!converter.IsValid(valueToValidate)) isCurrentPropertyValid = false; + } + else + { + if (value != null) + { + isCurrentPropertyValid = ValidateNestedProperty(type, (Dictionary)value); + } + } + + return isCurrentPropertyValid; + } + } } \ No newline at end of file diff --git a/Nop.Plugin.Api/logo.jpg b/logo.jpg similarity index 100% rename from Nop.Plugin.Api/logo.jpg rename to logo.jpg diff --git a/Nop.Plugin.Api/plugin.json b/plugin.json similarity index 78% rename from Nop.Plugin.Api/plugin.json rename to plugin.json index d658f2d..9e98a74 100644 --- a/Nop.Plugin.Api/plugin.json +++ b/plugin.json @@ -1,11 +1,11 @@ -{ - "Group": "Api", - "FriendlyName": "Api plugin", - "SystemName": "Nop.Plugin.Api", - "Version": "4.1.0", - "SupportedVersions": [ "4.10" ], - "Author": "Nop-Templates team", - "DisplayOrder": -1, - "FileName": "Nop.Plugin.Api.dll", - "Description": "This plugin is Restfull API for nopCommerce" +{ + "Group": "Api", + "FriendlyName": "Api plugin", + "SystemName": "Nop.Plugin.Api", + "Version": "4.3.3", + "SupportedVersions": [ "4.30" ], + "Author": "Nop-Templates team", + "DisplayOrder": -1, + "FileName": "Nop.Plugin.Api.dll", + "Description": "This plugin is Restfull API for nopCommerce" } \ No newline at end of file