diff --git a/Controllers/APIController.cs b/Controllers/APIController.cs index 0ea823a..c7c4280 100644 --- a/Controllers/APIController.cs +++ b/Controllers/APIController.cs @@ -126,7 +126,14 @@ namespace CarCareTracker.Controllers } var apiResult = _vehicleLogic.GetVehicleInfo(vehicles); - return Json(apiResult); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(apiResult, StaticHelper.GetInvariantOption()); + } + else + { + return Json(apiResult); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpGet] @@ -157,7 +164,13 @@ namespace CarCareTracker.Controllers } var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -282,7 +295,14 @@ namespace CarCareTracker.Controllers } var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId); var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } + else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -408,7 +428,14 @@ namespace CarCareTracker.Controllers } var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId); var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } + else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -533,7 +560,14 @@ namespace CarCareTracker.Controllers return Json(response); } var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId).Select(x => new TaxRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } + else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -664,7 +698,14 @@ namespace CarCareTracker.Controllers vehicleRecords = _odometerLogic.AutoConvertOdometerRecord(vehicleRecords); } var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } + else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -785,7 +826,14 @@ namespace CarCareTracker.Controllers Notes = x.Notes, ExtraFields = x.ExtraFields }); - return Json(result); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(result, StaticHelper.GetInvariantOption()); + } + else + { + return Json(result); + } } [TypeFilter(typeof(CollaboratorFilter))] [HttpPost] @@ -919,7 +967,14 @@ namespace CarCareTracker.Controllers var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId); var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId); var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).Select(x=> new ReminderExportModel { Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString()}); - return Json(results); + if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) + { + return Json(results, StaticHelper.GetInvariantOption()); + } + else + { + return Json(results); + } } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] diff --git a/Helper/ConfigHelper.cs b/Helper/ConfigHelper.cs index a22321d..3fe8cfd 100644 --- a/Helper/ConfigHelper.cs +++ b/Helper/ConfigHelper.cs @@ -24,7 +24,8 @@ namespace CarCareTracker.Helper bool GetServerEnableShopSupplies(); string GetServerPostgresConnection(); string GetAllowedFileUploadExtensions(); - public bool DeleteUserConfig(int userId); + bool DeleteUserConfig(int userId); + bool GetInvariantApi(); } public class ConfigHelper : IConfigHelper { @@ -51,6 +52,10 @@ namespace CarCareTracker.Helper { return CheckBool(CheckString("LUBELOGGER_CUSTOM_WIDGETS")); } + public bool GetInvariantApi() + { + return CheckBool(CheckString("LUBELOGGER_INVARIANT_API")); + } public string GetMOTD() { var motd = CheckString("LUBELOGGER_MOTD"); diff --git a/Helper/StaticHelper.cs b/Helper/StaticHelper.cs index 9530a22..a5ee920 100644 --- a/Helper/StaticHelper.cs +++ b/Helper/StaticHelper.cs @@ -1,6 +1,7 @@ using CarCareTracker.Models; using CsvHelper; using System.Globalization; +using System.Text.Json; namespace CarCareTracker.Helper { @@ -622,6 +623,12 @@ namespace CarCareTracker.Helper return string.IsNullOrWhiteSpace(decorations) ? input.ToString("C2") : $"{input.ToString("C2")}{decorations}"; } } + public static JsonSerializerOptions GetInvariantOption() + { + var serializerOption = new JsonSerializerOptions(); + serializerOption.Converters.Add(new InvariantConverter()); + return serializerOption; + } public static void WriteGasRecordExportModel(CsvWriter _csv, IEnumerable genericRecords) { var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct(); diff --git a/Models/API/TypeConverter.cs b/Models/API/TypeConverter.cs index f0d8407..535d559 100644 --- a/Models/API/TypeConverter.cs +++ b/Models/API/TypeConverter.cs @@ -3,6 +3,21 @@ using System.Text.Json.Serialization; namespace CarCareTracker.Models { + public class DummyType + { + + } + class InvariantConverter : JsonConverter + { + public override void Write(Utf8JsonWriter writer, DummyType value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + public override DummyType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } class FromDateOptional: JsonConverter { public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -14,7 +29,7 @@ namespace CarCareTracker.Models } else if (tokenType == JsonTokenType.Number) { - if (reader.TryGetInt32(out int intInput)) + if (reader.TryGetInt64(out long intInput)) { return DateTimeOffset.FromUnixTimeSeconds(intInput).Date.ToShortDateString(); } @@ -23,7 +38,14 @@ namespace CarCareTracker.Models } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { - writer.WriteStringValue(value); + if (options.Converters.Any(x => x.Type == typeof(DummyType))) + { + writer.WriteStringValue(DateTime.Parse(value).ToString("yyyy-MM-dd")); + } + else + { + writer.WriteStringValue(value); + } } } class FromDecimalOptional : JsonConverter @@ -45,7 +67,13 @@ namespace CarCareTracker.Models } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { - writer.WriteStringValue(value); + if (options.Converters.Any(x=>x.Type == typeof(DummyType))) + { + writer.WriteNumberValue(decimal.Parse(value)); + } else + { + writer.WriteStringValue(value); + } } } class FromIntOptional : JsonConverter @@ -68,7 +96,14 @@ namespace CarCareTracker.Models } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { - writer.WriteStringValue(value); + if (options.Converters.Any(x => x.Type == typeof(DummyType))) + { + writer.WriteNumberValue(int.Parse(value)); + } + else + { + writer.WriteStringValue(value); + } } } class FromBoolOptional : JsonConverter @@ -90,7 +125,14 @@ namespace CarCareTracker.Models } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { - writer.WriteStringValue(value); + if (options.Converters.Any(x => x.Type == typeof(DummyType))) + { + writer.WriteBooleanValue(bool.Parse(value)); + } + else + { + writer.WriteStringValue(value); + } } } } diff --git a/Models/Shared/ImportModel.cs b/Models/Shared/ImportModel.cs index ef57a0e..df6cf7e 100644 --- a/Models/Shared/ImportModel.cs +++ b/Models/Shared/ImportModel.cs @@ -47,6 +47,7 @@ namespace CarCareTracker.Models } public class GenericRecordExportModel { + [JsonConverter(typeof(FromIntOptional))] public string Id { get; set; } [JsonConverter(typeof(FromDateOptional))] public string Date { get; set; } @@ -61,6 +62,7 @@ namespace CarCareTracker.Models } public class OdometerRecordExportModel { + [JsonConverter(typeof(FromIntOptional))] public string Id { get; set; } [JsonConverter(typeof(FromDateOptional))] public string Date { get; set; } @@ -74,6 +76,7 @@ namespace CarCareTracker.Models } public class TaxRecordExportModel { + [JsonConverter(typeof(FromIntOptional))] public string Id { get; set; } [JsonConverter(typeof(FromDateOptional))] public string Date { get; set; } @@ -86,6 +89,7 @@ namespace CarCareTracker.Models } public class GasRecordExportModel { + [JsonConverter(typeof(FromIntOptional))] public string Id { get; set; } [JsonConverter(typeof(FromDateOptional))] public string Date { get; set; } @@ -110,7 +114,9 @@ namespace CarCareTracker.Models public string Urgency { get; set; } public string Metric { get; set; } public string Notes { get; set; } + [JsonConverter(typeof(FromDateOptional))] public string DueDate { get; set; } + [JsonConverter(typeof(FromIntOptional))] public string DueOdometer { get; set; } } public class PlanRecordExportModel