Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Grand.Business.Core.Utilities.ExportImport;
using Grand.Domain.Orders;

namespace Grand.Business.Checkout.Services.ExportImpot;
namespace Grand.Business.Checkout.Services.ExportImport;

public class OrderSchemaProperty : ISchemaProperty<Order>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Grand.Business.Checkout.Services.CheckoutAttributes;
using Grand.Business.Checkout.Services.ExportImpot;
using Grand.Business.Checkout.Services.ExportImport;
using Grand.Business.Checkout.Services.GiftVouchers;
using Grand.Business.Checkout.Services.Orders;
using Grand.Business.Checkout.Services.Payments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,16 +318,11 @@ public async Task<IList<CustomAttribute>> GetParseContactAttributes(IList<Custom
var date = model.FirstOrDefault(x => x.Key == attribute.Id + "_day")?.Value;
var month = model.FirstOrDefault(x => x.Key == attribute.Id + "_month")?.Value;
var year = model.FirstOrDefault(x => x.Key == attribute.Id + "_year")?.Value;
DateTime? selectedDate = null;
try
{
selectedDate = new DateTime(int.Parse(year), int.Parse(month), int.Parse(date));
}
catch { }

if (selectedDate.HasValue)
if (int.TryParse(year, out var y) && y is >= 1 and <= 9999 &&
int.TryParse(month, out var m) && m is >= 1 and <= 12 &&
int.TryParse(date, out var d) && d >= 1 && d <= DateTime.DaysInMonth(y, m))
customAttributes = AddContactAttribute(customAttributes,
attribute, selectedDate.Value.ToString("D")).ToList();
attribute, new DateTime(y, m, d).ToString("D")).ToList();
}
break;
case AttributeControlType.FileUpload:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Grand.Business.Checkout.Services.ExportImpot;
using Grand.Business.Checkout.Services.ExportImport;
using Grand.Business.Core.Interfaces.Common.Directory;
using Grand.Domain.Common;
using Grand.Domain.Directory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,38 @@ public async Task GetParseContactAttributes_ReadsTheAttributesOfTheGivenAccess()
Assert.AreEqual("text", result[0].Value);
}

[TestMethod]
[DataRow("2024", "2", "29", true)]
[DataRow("2023", "2", "29", false)]
[DataRow("2024", "4", "30", true)]
[DataRow("2024", "4", "31", false)]
[DataRow("2024", "1", "0", false)]
[DataRow("2024", "0", "1", false)]
[DataRow("2024", "13", "1", false)]
[DataRow("1", "1", "1", true)]
[DataRow("0", "1", "1", false)]
[DataRow("9999", "12", "31", true)]
[DataRow("10000", "1", "1", false)]
[DataRow("abc", "1", "1", false)]
[DataRow(null, "1", "1", false)]
public async Task GetParseContactAttributes_Datepicker_AddsOnlyAValidDate(string year, string month, string day,
bool added)
{
var access = CatalogAccess.For(new Customer(), "store1");
_contactAttributeServiceMock.Setup(c => c.GetAllContactAttributes(access))
.ReturnsAsync([new ContactAttribute { Id = "date", AttributeControlType = AttributeControlType.Datepicker }]);
var model = new List<CustomAttribute> {
new() { Key = "date_month", Value = month },
new() { Key = "date_day", Value = day }
};
if (year != null)
model.Add(new CustomAttribute { Key = "date_year", Value = year });

var result = await _parser.GetParseContactAttributes(model, access);

Assert.AreEqual(added, result.Count == 1);
}

private async Task<string> FormatFileUpload(DomainHost host, Guid? downloadGuid = null)
{
var attribute = new ContactAttribute {
Expand Down
47 changes: 47 additions & 0 deletions src/Tests/Grand.Web.Tests/Models/DateParsingModelsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Grand.Web.Models.Blogs;
using Grand.Web.Models.Customer;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Grand.Web.Tests.Models;

[TestClass]
public class DateParsingModelsTests
{
[TestMethod]
[DataRow(2024, 2, 29, true)]
[DataRow(2023, 2, 29, false)]
[DataRow(2024, 13, 1, false)]
[DataRow(2024, 4, 31, false)]
[DataRow(0, 1, 1, false)]
public void ParseDateOfBirth_ReturnsADateOnlyWhenItExists(int year, int month, int day, bool valid)
{
var register = new RegisterModel { DateOfBirthYear = year, DateOfBirthMonth = month, DateOfBirthDay = day };
var info = new CustomerInfoModel { DateOfBirthYear = year, DateOfBirthMonth = month, DateOfBirthDay = day };

var expected = valid ? new DateTime(year, month, day) : (DateTime?)null;
Assert.AreEqual(expected, register.ParseDateOfBirth());
Assert.AreEqual(expected, info.ParseDateOfBirth());
}

[TestMethod]
public void ParseDateOfBirth_MissingPart_ReturnsNull()
{
Assert.IsNull(new RegisterModel { DateOfBirthYear = 2000, DateOfBirthMonth = 1 }.ParseDateOfBirth());
Assert.IsNull(new CustomerInfoModel { DateOfBirthYear = 2000, DateOfBirthDay = 1 }.ParseDateOfBirth());
}

[TestMethod]
[DataRow("2024-5", 2024, 5)]
[DataRow("2024-13", 0, 0)]
[DataRow("2024-0", 0, 0)]
[DataRow("abc-5", 0, 0)]
[DataRow("2024", 0, 0)]
[DataRow("", 0, 0)]
public void GetParsedMonth_ReturnsTheFirstDayOfAValidMonth(string month, int year, int expectedMonth)
{
var model = new BlogPagingFilteringModel { Month = month };

var expected = year > 0 ? new DateTime(year, expectedMonth, 1) : (DateTime?)null;
Assert.AreEqual(expected, model.GetParsedMonth());
}
}
43 changes: 38 additions & 5 deletions src/Web/Grand.Web.Admin/Controllers/PluginController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,15 @@ public IActionResult UploadPlugin(IFormFile zippedFile)
var message = translationService.GetResource("Admin.Plugins.Uploaded");
Success(message);
}
catch (Exception exc)
{
Error(exc);
return RedirectToAction("List");
}
Comment on lines +287 to +291
finally
{
// Delete temporary file
DeleteDirectory(tempDirectory);
DeleteTempDirectory(tempDirectory);
}

logger.LogInformation("The plugin has been uploaded by the user {CurrentCustomerEmail}",
Expand All @@ -299,6 +304,20 @@ public IActionResult UploadPlugin(IFormFile zippedFile)
return RedirectToAction("List");
}

private void DeleteTempDirectory(string tempDirectory)
{
try
{
DeleteDirectory(tempDirectory);
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
//the previous plugin version moved here can hold an assembly this process has loaded;
//it is not loaded from here on the next start and the next upload removes it
logger.LogWarning(ex, "The temporary upload folder {TempDirectory} could not be deleted", tempDirectory);
}
}

private void Upload(string archivePath)
{
var pluginsPath = Path.Combine(webHostEnvironment.ContentRootPath, CommonPath.Plugins);
Expand Down Expand Up @@ -374,13 +393,27 @@ private void Upload(string archivePath)

var pathToUpload = Path.Combine(pluginsPath, uploadedItemDirectoryName);

try
if (!Directory.Exists(pathToUpload))
{
DeleteDirectory(pathToUpload);
ZipFile.ExtractToDirectory(archivePath, pluginsPath);
return;
}
catch { }

ZipFile.ExtractToDirectory(archivePath, pluginsPath);
//move the previous version into the temp upload folder instead of deleting it in place:
//a locked assembly fails the move before anything is changed, and a failed extraction puts it back
var previousVersionPath = Path.Combine(Path.GetDirectoryName(archivePath)!, Guid.NewGuid().ToString());
Directory.Move(pathToUpload, previousVersionPath);
try
{
ZipFile.ExtractToDirectory(archivePath, pluginsPath);
}
catch
{
if (Directory.Exists(pathToUpload))
DeleteDirectory(pathToUpload);
Directory.Move(previousVersionPath, pathToUpload);
throw;
}
}

#endregion
Expand Down
16 changes: 3 additions & 13 deletions src/Web/Grand.Web.Admin/Controllers/SystemController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,10 @@ public async Task<IActionResult> SystemInfo()
var model = new SystemInfoModel {
GrandVersion = GrandVersion.FullVersion,
GitBranch = GrandVersion.GitBranch,
GitCommit = GrandVersion.GitCommit
GitCommit = GrandVersion.GitCommit,
OperatingSystem = RuntimeInformation.OSDescription,
AspNetInfo = RuntimeInformation.FrameworkDescription
};
try
{
model.OperatingSystem = RuntimeInformation.OSDescription;
}
catch (Exception) { }

try
{
model.AspNetInfo = RuntimeEnvironment.GetSystemVersion();
}
catch (Exception) { }

model.MachineName = Environment.MachineName;
model.WebRootPath = _webHostEnvironment.WebRootPath;
model.ContentRootPath = _webHostEnvironment.ContentRootPath;
Expand Down
14 changes: 4 additions & 10 deletions src/Web/Grand.Web.Models/Blogs/BlogPagingFilteringModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,13 @@ public class BlogPagingFilteringModel : BasePageableModel

public virtual DateTime? GetParsedMonth()
{
DateTime? result = null;
if (string.IsNullOrEmpty(Month)) return null;
var tempDate = Month.Split(['-']);
if (tempDate.Length != 2) return null;
int.TryParse(tempDate[0], out var year);
int.TryParse(tempDate[1], out var month);
try
{
result = new DateTime(year, month, 1);
}
catch { }

return result;
if (!int.TryParse(tempDate[0], out var year) || year is < 1 or > 9999) return null;
if (!int.TryParse(tempDate[1], out var month) || month is < 1 or > 12) return null;

return new DateTime(year, month, 1);
}

public virtual DateTime? GetFromMonth()
Expand Down
13 changes: 5 additions & 8 deletions src/Web/Grand.Web.Models/Customer/CustomerInfoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,11 @@ public class CustomerInfoModel : BaseModel
if (!DateOfBirthYear.HasValue || !DateOfBirthMonth.HasValue || !DateOfBirthDay.HasValue)
return null;

DateTime? dateOfBirth = null;
try
{
dateOfBirth = new DateTime(DateOfBirthYear.Value, DateOfBirthMonth.Value, DateOfBirthDay.Value);
}
catch { }

return dateOfBirth;
int year = DateOfBirthYear.Value, month = DateOfBirthMonth.Value, day = DateOfBirthDay.Value;
if (year is < 1 or > 9999 || month is < 1 or > 12 || day < 1 || day > DateTime.DaysInMonth(year, month))
return null;

return new DateTime(year, month, day);
}


Expand Down
13 changes: 5 additions & 8 deletions src/Web/Grand.Web.Models/Customer/RegisterModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,10 @@ public class RegisterModel : BaseModel
if (!DateOfBirthYear.HasValue || !DateOfBirthMonth.HasValue || !DateOfBirthDay.HasValue)
return null;

DateTime? dateOfBirth = null;
try
{
dateOfBirth = new DateTime(DateOfBirthYear.Value, DateOfBirthMonth.Value, DateOfBirthDay.Value);
}
catch { }

return dateOfBirth;
int year = DateOfBirthYear.Value, month = DateOfBirthMonth.Value, day = DateOfBirthDay.Value;
if (year is < 1 or > 9999 || month is < 1 or > 12 || day < 1 || day > DateTime.DaysInMonth(year, month))
return null;

return new DateTime(year, month, day);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,11 @@ private async Task<IList<CustomAttribute>> ParseContactAttributes(ContactAttribu
var date = request.Attributes.FirstOrDefault(x => x.Key == attribute.Id + "_day")?.Value;
var month = request.Attributes.FirstOrDefault(x => x.Key == attribute.Id + "_month")?.Value;
var year = request.Attributes.FirstOrDefault(x => x.Key == attribute.Id + "_year")?.Value;
DateTime? selectedDate = null;
try
{
selectedDate = new DateTime(int.Parse(year), int.Parse(month), int.Parse(date));
}
catch
{
// ignored
}

if (selectedDate.HasValue)
if (int.TryParse(year, out var y) && y is >= 1 and <= 9999 &&
int.TryParse(month, out var m) && m is >= 1 and <= 12 &&
int.TryParse(date, out var d) && d >= 1 && d <= DateTime.DaysInMonth(y, m))
customAttributes = _contactAttributeParser.AddContactAttribute(customAttributes,
attribute, selectedDate.Value.ToString("D")).ToList();
attribute, new DateTime(y, m, d).ToString("D")).ToList();
}
break;
}
Expand Down
Loading