diff --git a/Controllers/APIController.cs b/Controllers/APIController.cs index 41a68b6..eba424d 100644 --- a/Controllers/APIController.cs +++ b/Controllers/APIController.cs @@ -1166,6 +1166,19 @@ namespace CarCareTracker.Controllers return Json(results); } } + [HttpGet] + [Route("/api/calendar")] + public IActionResult Calendar() + { + var vehiclesStored = _dataAccess.GetVehicles(); + if (!User.IsInRole(nameof(UserData.IsRootUser))) + { + vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID()); + } + var reminders = _vehicleLogic.GetReminders(vehiclesStored, true); + var calendarContent = StaticHelper.RemindersToCalendar(reminders); + return File(calendarContent, "text/calendar"); + } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] [Route("/api/vehicle/reminders/send")] diff --git a/Helper/StaticHelper.cs b/Helper/StaticHelper.cs index de1d975..f540ed7 100644 --- a/Helper/StaticHelper.cs +++ b/Helper/StaticHelper.cs @@ -1,6 +1,8 @@ using CarCareTracker.Models; using CsvHelper; using System.Globalization; +using System.Security.Cryptography; +using System.Text; using System.Text.Json; namespace CarCareTracker.Helper @@ -754,5 +756,52 @@ namespace CarCareTracker.Helper _csv.NextRecord(); } } + public static byte[] RemindersToCalendar(List reminders) + { + //converts reminders to iCal file + StringBuilder sb = new StringBuilder(); + //start the calendar item + sb.AppendLine("BEGIN:VCALENDAR"); + sb.AppendLine("VERSION:2.0"); + sb.AppendLine("PRODID:lubelogger.com"); + sb.AppendLine("CALSCALE:GREGORIAN"); + sb.AppendLine("METHOD:PUBLISH"); + + //create events. + foreach(ReminderRecordViewModel reminder in reminders) + { + var dtStart = reminder.Date.Date.ToString("yyyyMMddTHHmm00"); + var dtEnd = reminder.Date.Date.AddDays(1).AddMilliseconds(-1).ToString("yyyyMMddTHHmm00"); + var calendarUID = new Guid(MD5.HashData(Encoding.UTF8.GetBytes($"{dtStart}_{reminder.Description}"))); + sb.AppendLine("BEGIN:VEVENT"); + sb.AppendLine("DTSTAMP:" + DateTime.Now.ToString("yyyyMMddTHHmm00")); + sb.AppendLine("UID:" + calendarUID); + sb.AppendLine("DTSTART:" + dtStart); + sb.AppendLine("DTEND:" + dtEnd); + sb.AppendLine($"SUMMARY:{reminder.Description}"); + sb.AppendLine($"DESCRIPTION:{reminder.Description}"); + switch (reminder.Urgency) + { + case ReminderUrgency.NotUrgent: + sb.AppendLine("PRIORITY:3"); + break; + case ReminderUrgency.Urgent: + sb.AppendLine("PRIORITY:2"); + break; + case ReminderUrgency.VeryUrgent: + sb.AppendLine("PRIORITY:1"); + break; + case ReminderUrgency.PastDue: + sb.AppendLine("PRIORITY:1"); + break; + } + sb.AppendLine("END:VEVENT"); + } + + //end calendar item + sb.AppendLine("END:VCALENDAR"); + string calendarContent = sb.ToString(); + return Encoding.UTF8.GetBytes(calendarContent); + } } } diff --git a/Program.cs b/Program.cs index ce9346e..bcb25da 100644 --- a/Program.cs +++ b/Program.cs @@ -106,11 +106,15 @@ var app = builder.Build(); // Configure the HTTP request pipeline. app.UseExceptionHandler("/Home/Error"); +app.UseStaticFiles(); app.UseStaticFiles(new StaticFileOptions { + FileProvider = new PhysicalFileProvider( + Path.Combine(builder.Environment.ContentRootPath, "data", "images")), + RequestPath = "/images", OnPrepareResponse = ctx => { - if (ctx.Context.Request.Path.StartsWithSegments("/images") || ctx.Context.Request.Path.StartsWithSegments("/documents")) + if (ctx.Context.Request.Path.StartsWithSegments("/images")) { ctx.Context.Response.Headers.Add("Cache-Control", "no-store"); if (!ctx.Context.User.Identity.IsAuthenticated) @@ -121,16 +125,21 @@ app.UseStaticFiles(new StaticFileOptions } }); app.UseStaticFiles(new StaticFileOptions -{ - FileProvider = new PhysicalFileProvider( - Path.Combine(builder.Environment.ContentRootPath, "data", "images")), - RequestPath = "/images" -}); -app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(builder.Environment.ContentRootPath, "data", "documents")), - RequestPath = "/documents" + RequestPath = "/documents", + OnPrepareResponse = ctx => + { + if (ctx.Context.Request.Path.StartsWithSegments("/documents")) + { + ctx.Context.Response.Headers.Add("Cache-Control", "no-store"); + if (!ctx.Context.User.Identity.IsAuthenticated) + { + ctx.Context.Response.Redirect("/Login"); + } + } + } }); app.UseStaticFiles(new StaticFileOptions { @@ -142,7 +151,18 @@ app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(builder.Environment.ContentRootPath, "data", "temp")), - RequestPath = "/temp" + RequestPath = "/temp", + OnPrepareResponse = ctx => + { + if (ctx.Context.Request.Path.StartsWithSegments("/temp")) + { + ctx.Context.Response.Headers.Add("Cache-Control", "no-store"); + if (!ctx.Context.User.Identity.IsAuthenticated) + { + ctx.Context.Response.Redirect("/Login"); + } + } + } }); app.UseRouting(); diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 43c2773..25cbfec 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -34,6 +34,7 @@ @ViewData["Title"] - LubeLogger +