Merge pull request #916 from hargata/Hargata/oidc.userinfo
V1.4.7 Changes
This commit is contained in:
@@ -256,6 +256,15 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
||||||
}
|
}
|
||||||
|
//hardening - turns null values for List types into empty lists.
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var planRecord = new PlanRecord()
|
var planRecord = new PlanRecord()
|
||||||
@@ -346,6 +355,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -429,6 +446,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var serviceRecord = new ServiceRecord()
|
var serviceRecord = new ServiceRecord()
|
||||||
@@ -509,6 +534,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -591,6 +624,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var repairRecord = new CollisionRecord()
|
var repairRecord = new CollisionRecord()
|
||||||
@@ -672,6 +713,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -755,6 +804,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var upgradeRecord = new UpgradeRecord()
|
var upgradeRecord = new UpgradeRecord()
|
||||||
@@ -835,6 +892,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, Odometer, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -951,6 +1016,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, Description, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, Description, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var taxRecord = new TaxRecord()
|
var taxRecord = new TaxRecord()
|
||||||
@@ -1014,6 +1087,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -1113,6 +1194,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, and Odometer cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, and Odometer cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var odometerRecord = new OdometerRecord()
|
var odometerRecord = new OdometerRecord()
|
||||||
@@ -1174,6 +1263,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Initial Odometer, and Odometer cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Initial Odometer, and Odometer cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -1273,6 +1370,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Date, Odometer, FuelConsumed, IsFillToFull, MissedFuelUp, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Date, Odometer, FuelConsumed, IsFillToFull, MissedFuelUp, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var gasRecord = new GasRecord()
|
var gasRecord = new GasRecord()
|
||||||
@@ -1352,6 +1457,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Response.StatusCode = 400;
|
Response.StatusCode = 400;
|
||||||
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Odometer, FuelConsumed, IsFillToFull, MissedFuelUp, and Cost cannot be empty."));
|
return Json(OperationResponse.Failed("Input object invalid, Id, Date, Odometer, FuelConsumed, IsFillToFull, MissedFuelUp, and Cost cannot be empty."));
|
||||||
}
|
}
|
||||||
|
if (input.Files == null)
|
||||||
|
{
|
||||||
|
input.Files = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
if (input.ExtraFields == null)
|
||||||
|
{
|
||||||
|
input.ExtraFields = new List<ExtraField>();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//retrieve existing record
|
//retrieve existing record
|
||||||
@@ -1391,6 +1504,7 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
#region ReminderRecord
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("/api/vehicle/reminders")]
|
[Route("/api/vehicle/reminders")]
|
||||||
@@ -1403,7 +1517,7 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(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()});
|
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).Select(x=> new ReminderExportModel { Id = x.Id.ToString(), Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString(), Tags = string.Join(' ', x.Tags) });
|
||||||
if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant"))
|
if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant"))
|
||||||
{
|
{
|
||||||
return Json(results, StaticHelper.GetInvariantOption());
|
return Json(results, StaticHelper.GetInvariantOption());
|
||||||
@@ -1413,6 +1527,183 @@ namespace CarCareTracker.Controllers
|
|||||||
return Json(results);
|
return Json(results);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("/api/vehicle/reminders/add")]
|
||||||
|
[Consumes("application/json")]
|
||||||
|
public IActionResult AddReminderRecordJson(int vehicleId, [FromBody] ReminderExportModel input) => AddReminderRecord(vehicleId, input);
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("/api/vehicle/reminders/add")]
|
||||||
|
public IActionResult AddReminderRecord(int vehicleId, ReminderExportModel input)
|
||||||
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Must provide a valid vehicle id"));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(input.Description) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Metric))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Description and Metric cannot be empty."));
|
||||||
|
}
|
||||||
|
bool validMetric = Enum.TryParse(input.Metric, out ReminderMetric parsedMetric);
|
||||||
|
bool validDate = DateTime.TryParse(input.DueDate, out DateTime parsedDate);
|
||||||
|
bool validOdometer = int.TryParse(input.DueOdometer, out int parsedOdometer);
|
||||||
|
if (!validMetric)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, values for Metric(Date, Odometer, Both) is invalid."));
|
||||||
|
}
|
||||||
|
//validate metrics
|
||||||
|
switch (parsedMetric)
|
||||||
|
{
|
||||||
|
case ReminderMetric.Both:
|
||||||
|
//validate due date and odometer
|
||||||
|
if (!validDate || !validOdometer)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueDate and DueOdometer must be valid if Metric is Both"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ReminderMetric.Date:
|
||||||
|
if (!validDate)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueDate must be valid if Metric is Date"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ReminderMetric.Odometer:
|
||||||
|
if (!validOdometer)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueOdometer must be valid if Metric is Odometer"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var reminderRecord = new ReminderRecord()
|
||||||
|
{
|
||||||
|
VehicleId = vehicleId,
|
||||||
|
Description = input.Description,
|
||||||
|
Mileage = parsedOdometer,
|
||||||
|
Date = parsedDate,
|
||||||
|
Metric = parsedMetric,
|
||||||
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
|
Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List<string>() : input.Tags.Split(' ').Distinct().ToList()
|
||||||
|
};
|
||||||
|
_reminderRecordDataAccess.SaveReminderRecordToVehicle(reminderRecord);
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromReminderRecord(reminderRecord, "reminderrecord.add.api", User.Identity.Name));
|
||||||
|
return Json(OperationResponse.Succeed("Reminder Record Added"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 500;
|
||||||
|
return Json(OperationResponse.Failed(ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpPut]
|
||||||
|
[Route("/api/vehicle/reminders/update")]
|
||||||
|
[Consumes("application/json")]
|
||||||
|
public IActionResult UpdateReminderRecordJson([FromBody] ReminderExportModel input) => UpdateReminderRecord(input);
|
||||||
|
[HttpPut]
|
||||||
|
[Route("/api/vehicle/reminders/update")]
|
||||||
|
public IActionResult UpdateReminderRecord(ReminderExportModel input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.Id) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Description) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Metric))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Id, Description and Metric cannot be empty."));
|
||||||
|
}
|
||||||
|
bool validMetric = Enum.TryParse(input.Metric, out ReminderMetric parsedMetric);
|
||||||
|
bool validDate = DateTime.TryParse(input.DueDate, out DateTime parsedDate);
|
||||||
|
bool validOdometer = int.TryParse(input.DueOdometer, out int parsedOdometer);
|
||||||
|
if (!validMetric)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, values for Metric(Date, Odometer, Both) is invalid."));
|
||||||
|
}
|
||||||
|
//validate metrics
|
||||||
|
switch (parsedMetric)
|
||||||
|
{
|
||||||
|
case ReminderMetric.Both:
|
||||||
|
//validate due date and odometer
|
||||||
|
if (!validDate || !validOdometer)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueDate and DueOdometer must be valid if Metric is Both"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ReminderMetric.Date:
|
||||||
|
if (!validDate)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueDate must be valid if Metric is Date"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ReminderMetric.Odometer:
|
||||||
|
if (!validOdometer)
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, DueOdometer must be valid if Metric is Odometer"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//retrieve existing record
|
||||||
|
var existingRecord = _reminderRecordDataAccess.GetReminderRecordById(int.Parse(input.Id));
|
||||||
|
if (existingRecord != null && existingRecord.Id == int.Parse(input.Id))
|
||||||
|
{
|
||||||
|
//check if user has access to the vehicleId
|
||||||
|
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 401;
|
||||||
|
return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle."));
|
||||||
|
}
|
||||||
|
existingRecord.Date = parsedDate;
|
||||||
|
existingRecord.Mileage = parsedOdometer;
|
||||||
|
existingRecord.Description = input.Description;
|
||||||
|
existingRecord.Metric = parsedMetric;
|
||||||
|
existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes;
|
||||||
|
existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List<string>() : input.Tags.Split(' ').Distinct().ToList();
|
||||||
|
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingRecord);
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromReminderRecord(existingRecord, "reminderrecord.update.api", User.Identity.Name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Invalid Record Id"));
|
||||||
|
}
|
||||||
|
return Json(OperationResponse.Succeed("Reminder Record Updated"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 500;
|
||||||
|
return Json(OperationResponse.Failed(ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("/api/vehicle/reminders/delete")]
|
||||||
|
public IActionResult DeleteReminderRecord(int id)
|
||||||
|
{
|
||||||
|
var existingRecord = _reminderRecordDataAccess.GetReminderRecordById(id);
|
||||||
|
if (existingRecord == null || existingRecord.Id == default)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Invalid Record Id"));
|
||||||
|
}
|
||||||
|
//security check.
|
||||||
|
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 401;
|
||||||
|
return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle."));
|
||||||
|
}
|
||||||
|
var result = _reminderRecordDataAccess.DeleteReminderRecordById(existingRecord.Id);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromReminderRecord(existingRecord, "reminderrecord.delete.api", User.Identity.Name));
|
||||||
|
}
|
||||||
|
return Json(OperationResponse.Conditional(result, "Reminder Record Deleted"));
|
||||||
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("/api/calendar")]
|
[Route("/api/calendar")]
|
||||||
public IActionResult Calendar()
|
public IActionResult Calendar()
|
||||||
@@ -1426,6 +1717,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var calendarContent = StaticHelper.RemindersToCalendar(reminders);
|
var calendarContent = StaticHelper.RemindersToCalendar(reminders);
|
||||||
return File(calendarContent, "text/calendar");
|
return File(calendarContent, "text/calendar");
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("/api/documents/upload")]
|
[Route("/api/documents/upload")]
|
||||||
public IActionResult UploadDocument(List<IFormFile> documents)
|
public IActionResult UploadDocument(List<IFormFile> documents)
|
||||||
|
|||||||
@@ -49,21 +49,31 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
return View(model: redirectURL);
|
return View(model: redirectURL);
|
||||||
}
|
}
|
||||||
public IActionResult Registration()
|
public IActionResult Registration(string token = "", string email = "")
|
||||||
{
|
{
|
||||||
if (_config.GetServerDisabledRegistration())
|
if (_config.GetServerDisabledRegistration())
|
||||||
{
|
{
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
return View();
|
var viewModel = new LoginModel
|
||||||
|
{
|
||||||
|
EmailAddress = string.IsNullOrWhiteSpace(email) ? string.Empty : email,
|
||||||
|
Token = string.IsNullOrWhiteSpace(token) ? string.Empty : token
|
||||||
|
};
|
||||||
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
public IActionResult ForgotPassword()
|
public IActionResult ForgotPassword()
|
||||||
{
|
{
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
public IActionResult ResetPassword()
|
public IActionResult ResetPassword(string token = "", string email = "")
|
||||||
{
|
{
|
||||||
return View();
|
var viewModel = new LoginModel
|
||||||
|
{
|
||||||
|
EmailAddress = string.IsNullOrWhiteSpace(email) ? string.Empty : email,
|
||||||
|
Token = string.IsNullOrWhiteSpace(token) ? string.Empty : token
|
||||||
|
};
|
||||||
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
public IActionResult GetRemoteLoginLink()
|
public IActionResult GetRemoteLoginLink()
|
||||||
{
|
{
|
||||||
@@ -130,7 +140,9 @@ namespace CarCareTracker.Controllers
|
|||||||
Content = new FormUrlEncodedContent(httpParams)
|
Content = new FormUrlEncodedContent(httpParams)
|
||||||
};
|
};
|
||||||
var tokenResult = await httpClient.SendAsync(httpRequest).Result.Content.ReadAsStringAsync();
|
var tokenResult = await httpClient.SendAsync(httpRequest).Result.Content.ReadAsStringAsync();
|
||||||
var userJwt = JsonSerializer.Deserialize<OpenIDResult>(tokenResult)?.id_token ?? string.Empty;
|
var decodedToken = JsonSerializer.Deserialize<OpenIDResult>(tokenResult);
|
||||||
|
var userJwt = decodedToken?.id_token ?? string.Empty;
|
||||||
|
var userAccessToken = decodedToken?.access_token ?? string.Empty;
|
||||||
if (!string.IsNullOrWhiteSpace(userJwt))
|
if (!string.IsNullOrWhiteSpace(userJwt))
|
||||||
{
|
{
|
||||||
//validate JWT token
|
//validate JWT token
|
||||||
@@ -140,7 +152,23 @@ namespace CarCareTracker.Controllers
|
|||||||
if (parsedToken.Claims.Any(x => x.Type == "email"))
|
if (parsedToken.Claims.Any(x => x.Type == "email"))
|
||||||
{
|
{
|
||||||
userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
||||||
} else
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(openIdConfig.UserInfoURL) && !string.IsNullOrWhiteSpace(userAccessToken))
|
||||||
|
{
|
||||||
|
//retrieve claims from userinfo endpoint if no email claims are returned within id_token
|
||||||
|
var userInfoHttpRequest = new HttpRequestMessage(HttpMethod.Get, openIdConfig.UserInfoURL);
|
||||||
|
userInfoHttpRequest.Headers.Add("Authorization", $"Bearer {userAccessToken}");
|
||||||
|
var userInfoResult = await httpClient.SendAsync(userInfoHttpRequest).Result.Content.ReadAsStringAsync();
|
||||||
|
var userInfo = JsonSerializer.Deserialize<OpenIDUserInfo>(userInfoResult);
|
||||||
|
if (!string.IsNullOrWhiteSpace(userInfo?.email ?? string.Empty))
|
||||||
|
{
|
||||||
|
userEmailAddress = userInfo?.email ?? string.Empty;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
_logger.LogError($"OpenID Provider did not provide an email claim via UserInfo endpoint");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var returnedClaims = parsedToken.Claims.Select(x => x.Type);
|
var returnedClaims = parsedToken.Claims.Select(x => x.Type);
|
||||||
_logger.LogError($"OpenID Provider did not provide an email claim, claims returned: {string.Join(",", returnedClaims)}");
|
_logger.LogError($"OpenID Provider did not provide an email claim, claims returned: {string.Join(",", returnedClaims)}");
|
||||||
@@ -239,7 +267,9 @@ namespace CarCareTracker.Controllers
|
|||||||
Content = new FormUrlEncodedContent(httpParams)
|
Content = new FormUrlEncodedContent(httpParams)
|
||||||
};
|
};
|
||||||
var tokenResult = await httpClient.SendAsync(httpRequest).Result.Content.ReadAsStringAsync();
|
var tokenResult = await httpClient.SendAsync(httpRequest).Result.Content.ReadAsStringAsync();
|
||||||
var userJwt = JsonSerializer.Deserialize<OpenIDResult>(tokenResult)?.id_token ?? string.Empty;
|
var decodedToken = JsonSerializer.Deserialize<OpenIDResult>(tokenResult);
|
||||||
|
var userJwt = decodedToken?.id_token ?? string.Empty;
|
||||||
|
var userAccessToken = decodedToken?.access_token ?? string.Empty;
|
||||||
if (!string.IsNullOrWhiteSpace(userJwt))
|
if (!string.IsNullOrWhiteSpace(userJwt))
|
||||||
{
|
{
|
||||||
results.Add(OperationResponse.Succeed($"Passed JWT Parsing - id_token: {userJwt}"));
|
results.Add(OperationResponse.Succeed($"Passed JWT Parsing - id_token: {userJwt}"));
|
||||||
@@ -252,6 +282,22 @@ namespace CarCareTracker.Controllers
|
|||||||
userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
||||||
results.Add(OperationResponse.Succeed($"Passed Claim Validation - email"));
|
results.Add(OperationResponse.Succeed($"Passed Claim Validation - email"));
|
||||||
}
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(openIdConfig.UserInfoURL) && !string.IsNullOrWhiteSpace(userAccessToken))
|
||||||
|
{
|
||||||
|
//retrieve claims from userinfo endpoint if no email claims are returned within id_token
|
||||||
|
var userInfoHttpRequest = new HttpRequestMessage(HttpMethod.Get, openIdConfig.UserInfoURL);
|
||||||
|
userInfoHttpRequest.Headers.Add("Authorization", $"Bearer {userAccessToken}");
|
||||||
|
var userInfoResult = await httpClient.SendAsync(userInfoHttpRequest).Result.Content.ReadAsStringAsync();
|
||||||
|
var userInfo = JsonSerializer.Deserialize<OpenIDUserInfo>(userInfoResult);
|
||||||
|
if (!string.IsNullOrWhiteSpace(userInfo?.email ?? string.Empty))
|
||||||
|
{
|
||||||
|
userEmailAddress = userInfo?.email ?? string.Empty;
|
||||||
|
results.Add(OperationResponse.Succeed($"Passed Claim Validation - Retrieved email via UserInfo endpoint"));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
results.Add(OperationResponse.Failed($"Failed Claim Validation - Unable to retrieve email via UserInfo endpoint: {openIdConfig.UserInfoURL} using access_token: {userAccessToken} - Received {userInfoResult}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var returnedClaims = parsedToken.Claims.Select(x => x.Type);
|
var returnedClaims = parsedToken.Claims.Select(x => x.Type);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace CarCareTracker.Helper
|
|||||||
bool GetServerEnableShopSupplies();
|
bool GetServerEnableShopSupplies();
|
||||||
string GetServerPostgresConnection();
|
string GetServerPostgresConnection();
|
||||||
string GetAllowedFileUploadExtensions();
|
string GetAllowedFileUploadExtensions();
|
||||||
|
string GetServerDomain();
|
||||||
bool DeleteUserConfig(int userId);
|
bool DeleteUserConfig(int userId);
|
||||||
bool GetInvariantApi();
|
bool GetInvariantApi();
|
||||||
bool GetServerOpenRegistration();
|
bool GetServerOpenRegistration();
|
||||||
@@ -62,6 +63,11 @@ namespace CarCareTracker.Helper
|
|||||||
var motd = CheckString("LUBELOGGER_MOTD");
|
var motd = CheckString("LUBELOGGER_MOTD");
|
||||||
return motd;
|
return motd;
|
||||||
}
|
}
|
||||||
|
public string GetServerDomain()
|
||||||
|
{
|
||||||
|
var domain = CheckString("LUBELOGGER_DOMAIN");
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
public bool GetServerOpenRegistration()
|
public bool GetServerOpenRegistration()
|
||||||
{
|
{
|
||||||
return CheckBool(CheckString("LUBELOGGER_OPEN_REGISTRATION"));
|
return CheckBool(CheckString("LUBELOGGER_OPEN_REGISTRATION"));
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
private readonly MailConfig mailConfig;
|
private readonly MailConfig mailConfig;
|
||||||
private readonly string serverLanguage;
|
private readonly string serverLanguage;
|
||||||
|
private readonly string serverDomain;
|
||||||
private readonly IFileHelper _fileHelper;
|
private readonly IFileHelper _fileHelper;
|
||||||
private readonly ITranslationHelper _translator;
|
private readonly ITranslationHelper _translator;
|
||||||
private readonly ILogger<MailHelper> _logger;
|
private readonly ILogger<MailHelper> _logger;
|
||||||
@@ -29,6 +30,7 @@ namespace CarCareTracker.Helper
|
|||||||
//load mailConfig from Configuration
|
//load mailConfig from Configuration
|
||||||
mailConfig = config.GetMailConfig();
|
mailConfig = config.GetMailConfig();
|
||||||
serverLanguage = config.GetServerLanguage();
|
serverLanguage = config.GetServerLanguage();
|
||||||
|
serverDomain = config.GetServerDomain();
|
||||||
_fileHelper = fileHelper;
|
_fileHelper = fileHelper;
|
||||||
_translator = translationHelper;
|
_translator = translationHelper;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -43,7 +45,14 @@ namespace CarCareTracker.Helper
|
|||||||
return OperationResponse.Failed("Email Address or Token is invalid");
|
return OperationResponse.Failed("Email Address or Token is invalid");
|
||||||
}
|
}
|
||||||
string emailSubject = _translator.Translate(serverLanguage, "Your Registration Token for LubeLogger");
|
string emailSubject = _translator.Translate(serverLanguage, "Your Registration Token for LubeLogger");
|
||||||
string emailBody = $"{_translator.Translate(serverLanguage, "A token has been generated on your behalf, please complete your registration for LubeLogger using the token")}: {token}";
|
string tokenHtml = token;
|
||||||
|
if (!string.IsNullOrWhiteSpace(serverDomain))
|
||||||
|
{
|
||||||
|
string cleanedURL = serverDomain.EndsWith('/') ? serverDomain.TrimEnd('/') : serverDomain;
|
||||||
|
//construct registration URL.
|
||||||
|
tokenHtml = $"<a href='{cleanedURL}/Login/Registration?email={emailAddress}&token={token}' target='_blank'>{token}</a>";
|
||||||
|
}
|
||||||
|
string emailBody = $"<span>{_translator.Translate(serverLanguage, "A token has been generated on your behalf, please complete your registration for LubeLogger using the token")}: {tokenHtml}</span>";
|
||||||
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@@ -64,7 +73,14 @@ namespace CarCareTracker.Helper
|
|||||||
return OperationResponse.Failed("Email Address or Token is invalid");
|
return OperationResponse.Failed("Email Address or Token is invalid");
|
||||||
}
|
}
|
||||||
string emailSubject = _translator.Translate(serverLanguage, "Your Password Reset Token for LubeLogger");
|
string emailSubject = _translator.Translate(serverLanguage, "Your Password Reset Token for LubeLogger");
|
||||||
string emailBody = $"{_translator.Translate(serverLanguage, "A token has been generated on your behalf, please reset your password for LubeLogger using the token")}: {token}";
|
string tokenHtml = token;
|
||||||
|
if (!string.IsNullOrWhiteSpace(serverDomain))
|
||||||
|
{
|
||||||
|
string cleanedURL = serverDomain.EndsWith('/') ? serverDomain.TrimEnd('/') : serverDomain;
|
||||||
|
//construct registration URL.
|
||||||
|
tokenHtml = $"<a href='{cleanedURL}/Login/ResetPassword?email={emailAddress}&token={token}' target='_blank'>{token}</a>";
|
||||||
|
}
|
||||||
|
string emailBody = $"<span>{_translator.Translate(serverLanguage, "A token has been generated on your behalf, please reset your password for LubeLogger using the token")}: {tokenHtml}</span>";
|
||||||
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace CarCareTracker.Helper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StaticHelper
|
public static class StaticHelper
|
||||||
{
|
{
|
||||||
public const string VersionNumber = "1.4.6";
|
public const string VersionNumber = "1.4.7";
|
||||||
public const string DbName = "data/cartracker.db";
|
public const string DbName = "data/cartracker.db";
|
||||||
public const string UserConfigPath = "data/config/userConfig.json";
|
public const string UserConfigPath = "data/config/userConfig.json";
|
||||||
public const string LegacyUserConfigPath = "config/userConfig.json";
|
public const string LegacyUserConfigPath = "config/userConfig.json";
|
||||||
|
|||||||
@@ -303,11 +303,11 @@ namespace CarCareTracker.Logic
|
|||||||
//set next reminder
|
//set next reminder
|
||||||
if (results.Any(x => (x.Metric == ReminderMetric.Date || x.Metric == ReminderMetric.Both) && x.Date >= DateTime.Now.Date))
|
if (results.Any(x => (x.Metric == ReminderMetric.Date || x.Metric == ReminderMetric.Both) && x.Date >= DateTime.Now.Date))
|
||||||
{
|
{
|
||||||
resultToAdd.NextReminder = results.Where(x => x.Date >= DateTime.Now.Date).OrderBy(x => x.Date).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() }).First();
|
resultToAdd.NextReminder = results.Where(x => x.Date >= DateTime.Now.Date).OrderBy(x => x.Date).Select(x => new ReminderExportModel { Id = x.Id.ToString(), Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString(), Tags = string.Join(' ', x.Tags) }).First();
|
||||||
}
|
}
|
||||||
else if (results.Any(x => (x.Metric == ReminderMetric.Odometer || x.Metric == ReminderMetric.Both) && x.Mileage >= currentMileage))
|
else if (results.Any(x => (x.Metric == ReminderMetric.Odometer || x.Metric == ReminderMetric.Both) && x.Mileage >= currentMileage))
|
||||||
{
|
{
|
||||||
resultToAdd.NextReminder = results.Where(x => x.Mileage >= currentMileage).OrderBy(x => x.Mileage).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() }).First();
|
resultToAdd.NextReminder = results.Where(x => x.Mileage >= currentMileage).OrderBy(x => x.Mileage).Select(x => new ReminderExportModel { Id = x.Id.ToString(), Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString(), Tags = string.Join(' ', x.Tags) }).First();
|
||||||
}
|
}
|
||||||
apiResult.Add(resultToAdd);
|
apiResult.Add(resultToAdd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
public bool DisableRegularLogin { get; set; } = false;
|
public bool DisableRegularLogin { get; set; } = false;
|
||||||
public bool UsePKCE { get; set; } = false;
|
public bool UsePKCE { get; set; } = false;
|
||||||
public string LogOutURL { get; set; } = "";
|
public string LogOutURL { get; set; } = "";
|
||||||
|
public string UserInfoURL { get; set; } = "";
|
||||||
public string RemoteAuthURL { get {
|
public string RemoteAuthURL { get {
|
||||||
var redirectUrl = $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}";
|
var redirectUrl = $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}";
|
||||||
if (UsePKCE)
|
if (UsePKCE)
|
||||||
|
|||||||
@@ -3,5 +3,6 @@
|
|||||||
public class OpenIDResult
|
public class OpenIDResult
|
||||||
{
|
{
|
||||||
public string id_token { get; set; }
|
public string id_token { get; set; }
|
||||||
|
public string access_token { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
Models/OIDC/OpenIDUserInfo.cs
Normal file
7
Models/OIDC/OpenIDUserInfo.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class OpenIDUserInfo
|
||||||
|
{
|
||||||
|
public string email { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -115,6 +115,8 @@ namespace CarCareTracker.Models
|
|||||||
}
|
}
|
||||||
public class ReminderExportModel
|
public class ReminderExportModel
|
||||||
{
|
{
|
||||||
|
[JsonConverter(typeof(FromIntOptional))]
|
||||||
|
public string Id { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Urgency { get; set; }
|
public string Urgency { get; set; }
|
||||||
public string Metric { get; set; }
|
public string Metric { get; set; }
|
||||||
@@ -123,6 +125,7 @@ namespace CarCareTracker.Models
|
|||||||
public string DueDate { get; set; }
|
public string DueDate { get; set; }
|
||||||
[JsonConverter(typeof(FromIntOptional))]
|
[JsonConverter(typeof(FromIntOptional))]
|
||||||
public string DueOdometer { get; set; }
|
public string DueOdometer { get; set; }
|
||||||
|
public string Tags { get; set; }
|
||||||
}
|
}
|
||||||
public class PlanRecordExportModel
|
public class PlanRecordExportModel
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -669,6 +669,65 @@
|
|||||||
vehicleId - Id of Vehicle
|
vehicleId - Id of Vehicle
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge bg-primary">POST</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/reminders/add</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Adds Reminder Record to the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
<br />
|
||||||
|
Body(form-data): {<br />
|
||||||
|
description - Description<br />
|
||||||
|
dueDate - Due Date<br />
|
||||||
|
dueOdometer - Due Odometer reading<br />
|
||||||
|
metric - Date/Odometer/Both<br />
|
||||||
|
notes - notes(optional)<br />
|
||||||
|
tags - tags separated by space(optional)<br />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge text-bg-warning">PUT</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/reminders/update</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Updates Reminder Record
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Body(form-data): {<br />
|
||||||
|
Id - Id of Reminder Record<br />
|
||||||
|
description - Description<br />
|
||||||
|
dueDate - Due Date<br />
|
||||||
|
dueOdometer - Due Odometer reading<br />
|
||||||
|
metric - Date/Odometer/Both<br />
|
||||||
|
notes - notes(optional)<br />
|
||||||
|
tags - tags separated by space(optional)<br />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge text-bg-danger">DELETE</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/reminders/delete</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Deletes Reminder Record
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Id - Id of Reminder Record
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row api-method">
|
<div class="row api-method">
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<span class="badge bg-success">GET</span>
|
<span class="badge bg-success">GET</span>
|
||||||
|
|||||||
@@ -81,9 +81,9 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-6 garage-item-add">
|
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-6 garage-item-add user-select-none">
|
||||||
<div class="card" onclick="showAddVehicleModal()" style="height:100%;">
|
<div class="card" onclick="showAddVehicleModal()" style="height:100%;">
|
||||||
<img src="/defaults/addnew_vehicle.png" style="object-fit:scale-down;height:100%;" />
|
<img src="/defaults/addnew_vehicle.png" style="object-fit:scale-down;height:100%;pointer-events:none;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -165,6 +165,14 @@
|
|||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<input type="text" readonly id="inputOIDCToken" class="form-control" placeholder="@translator.Translate(userLanguage, "Not Configured")" value="@Model.OIDCConfig.TokenURL">
|
<input type="text" readonly id="inputOIDCToken" class="form-control" placeholder="@translator.Translate(userLanguage, "Not Configured")" value="@Model.OIDCConfig.TokenURL">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="col-md-6 col-12">
|
||||||
|
<label for="inputOIDCUserInfo">@translator.Translate(userLanguage, "OIDC UserInfo URL")</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-12">
|
||||||
|
<input type="text" readonly id="inputOIDCUserInfo" class="form-control" placeholder="@translator.Translate(userLanguage, "Not Configured")" value="@Model.OIDCConfig.UserInfoURL">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
var userLanguage = config.GetServerLanguage();
|
var userLanguage = config.GetServerLanguage();
|
||||||
var openRegistrationEnabled = config.GetServerOpenRegistration();
|
var openRegistrationEnabled = config.GetServerOpenRegistration();
|
||||||
}
|
}
|
||||||
|
@model LoginModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Register";
|
ViewData["Title"] = "Register";
|
||||||
}
|
}
|
||||||
@@ -19,18 +20,18 @@
|
|||||||
<label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
|
<label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
|
||||||
@if (openRegistrationEnabled) {
|
@if (openRegistrationEnabled) {
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="inputToken" class="form-control">
|
<input type="text" id="inputToken" class="form-control" value="@Model.Token">
|
||||||
<div class="input-group-text">
|
<div class="input-group-text">
|
||||||
<button type="button" class="btn btn-sm text-secondary password-visible-button" onclick="sendRegistrationToken()"><i class="bi bi-send"></i></button>
|
<button type="button" class="btn btn-sm text-secondary password-visible-button" onclick="sendRegistrationToken()"><i class="bi bi-send"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} else {
|
} else {
|
||||||
<input type="text" id="inputToken" class="form-control">
|
<input type="text" id="inputToken" class="form-control" value="@Model.Token">
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputEmail">@translator.Translate(userLanguage, "Email Address")</label>
|
<label for="inputEmail">@translator.Translate(userLanguage, "Email Address")</label>
|
||||||
<input type="text" id="inputEmail" class="form-control">
|
<input type="text" id="inputEmail" class="form-control" value="@Model.EmailAddress">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputUserName">@translator.Translate(userLanguage, "Username")</label>
|
<label for="inputUserName">@translator.Translate(userLanguage, "Username")</label>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
@{
|
@{
|
||||||
var userLanguage = config.GetServerLanguage();
|
var userLanguage = config.GetServerLanguage();
|
||||||
}
|
}
|
||||||
|
@model LoginModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Reset Password";
|
ViewData["Title"] = "Reset Password";
|
||||||
}
|
}
|
||||||
@@ -16,11 +17,11 @@
|
|||||||
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
|
<label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
|
||||||
<input type="text" id="inputToken" class="form-control">
|
<input type="text" id="inputToken" class="form-control" value="@Model.Token">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputUserName">@translator.Translate(userLanguage, "Email Address")</label>
|
<label for="inputUserName">@translator.Translate(userLanguage, "Email Address")</label>
|
||||||
<input type="text" id="inputEmail" class="form-control">
|
<input type="text" id="inputEmail" class="form-control" value="@Model.EmailAddress">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputUserPassword">@translator.Translate(userLanguage, "New Password")</label>
|
<label for="inputUserPassword">@translator.Translate(userLanguage, "New Password")</label>
|
||||||
|
|||||||
49
Views/Vehicle/_ExtraFieldMultiple.cshtml
Normal file
49
Views/Vehicle/_ExtraFieldMultiple.cshtml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
}
|
||||||
|
@model List<ExtraField>
|
||||||
|
@if (Model.Any()){
|
||||||
|
@foreach (ExtraField field in Model)
|
||||||
|
{
|
||||||
|
var elementId = Guid.NewGuid();
|
||||||
|
<div class="extra-field">
|
||||||
|
<label for="@elementId">@field.Name</label>
|
||||||
|
@switch(field.FieldType){
|
||||||
|
case (ExtraFieldType.Text):
|
||||||
|
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
break;
|
||||||
|
case (ExtraFieldType.Number):
|
||||||
|
<input type="number" inputmode="numeric" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
break;
|
||||||
|
case (ExtraFieldType.Decimal):
|
||||||
|
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="fixDecimalInput(this, 2)" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
break;
|
||||||
|
case (ExtraFieldType.Date):
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||||
|
</div>
|
||||||
|
<script>initExtraFieldDatePicker('@elementId')</script>
|
||||||
|
break;
|
||||||
|
case (ExtraFieldType.Time):
|
||||||
|
<input type="time" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
break;
|
||||||
|
case (ExtraFieldType.Location):
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="populateLocationField('@elementId')"><i class="bi bi-geo-alt"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
{
|
{
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<a type="button" class="btn btn-link text-truncate uploadedFileName" href="@filesUploaded.Location" target="_blank">@filesUploaded.Name</a>
|
<a type="button" class="btn btn-link text-truncate uploadedFileName" href="@filesUploaded.Location" title="@filesUploaded.Name" target="_blank">@filesUploaded.Name</a>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="editFileName('@filesUploaded.Location', this)"><i class="bi bi-pencil"></i></button>
|
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="editFileName('@filesUploaded.Location', this)"><i class="bi bi-pencil"></i></button>
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteFileFromUploadedFiles('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteFileFromUploadedFiles('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
||||||
|
|||||||
@@ -97,14 +97,7 @@
|
|||||||
<!option value="@tag">@tag</!option>
|
<!option value="@tag">@tag</!option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
@foreach (ExtraField field in Model.GasRecord.ExtraFields)
|
@await Html.PartialAsync("_ExtraField", Model.GasRecord.ExtraFields)
|
||||||
{
|
|
||||||
var elementId = Guid.NewGuid();
|
|
||||||
<div class="extra-field">
|
|
||||||
<label for="@elementId">@field.Name</label>
|
|
||||||
<input type="text" id="@elementId" class="form-control @(field.IsRequired ? "extra-field-required" : "")" placeholder="@field.Name" value="@field.Value">
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<label for="gasRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
<label for="gasRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||||
|
|||||||
@@ -30,14 +30,7 @@
|
|||||||
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
<label for="gasRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
<label for="gasRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
||||||
<select multiple class="form-select" id="gasRecordTag"></select>
|
<select multiple class="form-select" id="gasRecordTag"></select>
|
||||||
@foreach (ExtraField field in Model.EditRecord.ExtraFields)
|
@await Html.PartialAsync("_ExtraFieldMultiple", Model.EditRecord.ExtraFields)
|
||||||
{
|
|
||||||
var elementId = Guid.NewGuid();
|
|
||||||
<div class="extra-field">
|
|
||||||
<label for="@elementId">@field.Name</label>
|
|
||||||
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<label for="gasRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
<label for="gasRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||||
|
|||||||
@@ -28,14 +28,7 @@
|
|||||||
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="fixDecimalInput(this, 2)" id="genericRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="fixDecimalInput(this, 2)" id="genericRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
<label for="genericRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
<label for="genericRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
||||||
<select multiple class="form-select" id="genericRecordTag"></select>
|
<select multiple class="form-select" id="genericRecordTag"></select>
|
||||||
@foreach (ExtraField field in Model.EditRecord.ExtraFields)
|
@await Html.PartialAsync("_ExtraFieldMultiple", Model.EditRecord.ExtraFields)
|
||||||
{
|
|
||||||
var elementId = Guid.NewGuid();
|
|
||||||
<div class="extra-field">
|
|
||||||
<label for="@elementId">@field.Name</label>
|
|
||||||
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<label for="genericRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
<label for="genericRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||||
|
|||||||
@@ -26,14 +26,7 @@
|
|||||||
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
||||||
<label for="odometerRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
<label for="odometerRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
|
||||||
<select multiple class="form-select" id="odometerRecordTag"></select>
|
<select multiple class="form-select" id="odometerRecordTag"></select>
|
||||||
@foreach (ExtraField field in Model.EditRecord.ExtraFields)
|
@await Html.PartialAsync("_ExtraFieldMultiple", Model.EditRecord.ExtraFields)
|
||||||
{
|
|
||||||
var elementId = Guid.NewGuid();
|
|
||||||
<div class="extra-field">
|
|
||||||
<label for="@elementId">@field.Name</label>
|
|
||||||
<input type="text" id="@elementId" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<label for="odometerRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
<label for="odometerRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row swimlane">
|
<div class="row swimlane">
|
||||||
<div class="col-3 d-flex flex-column swimlane mid" ondragover="dragOver(event)" ondrop="dropBox(event, 'Backlog')">
|
<div class="col-3 d-flex flex-column swimlane" ondragover="dragOver(event)" ondrop="dropBox(event, 'Backlog')">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||||
<span class="display-7">@translator.Translate(userLanguage,"Planned")</span>
|
<span class="display-7">@translator.Translate(userLanguage,"Planned")</span>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
@await Html.PartialAsync("_PlanRecordItem", planRecord)
|
@await Html.PartialAsync("_PlanRecordItem", planRecord)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 d-flex flex-column swimlane mid" ondragover="dragOver(event)" ondrop="dropBox(event, 'InProgress')">
|
<div class="col-3 d-flex flex-column swimlane" ondragover="dragOver(event)" ondrop="dropBox(event, 'InProgress')">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||||
<span class="display-7">@translator.Translate(userLanguage,"Doing")</span>
|
<span class="display-7">@translator.Translate(userLanguage,"Doing")</span>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
@await Html.PartialAsync("_PlanRecordItem", planRecord)
|
@await Html.PartialAsync("_PlanRecordItem", planRecord)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 d-flex flex-column swimlane end" ondragover="dragOver(event)" ondrop="dropBox(event, 'Done')">
|
<div class="col-3 d-flex flex-column swimlane" ondragover="dragOver(event)" ondrop="dropBox(event, 'Done')">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||||
<span class="display-7">@translator.Translate(userLanguage,"Done")</span>
|
<span class="display-7">@translator.Translate(userLanguage,"Done")</span>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
{
|
{
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<a type="button" class="btn btn-link text-truncate uploadedFileName" href="@filesUploaded.Location" target="_blank">@filesUploaded.Name</a>
|
<a type="button" class="btn btn-link text-truncate uploadedFileName" href="@filesUploaded.Location" title="@filesUploaded.Name" target="_blank">@filesUploaded.Name</a>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="editFileName('@filesUploaded.Location', this)"><i class="bi bi-pencil"></i></button>
|
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="editFileName('@filesUploaded.Location', this)"><i class="bi bi-pencil"></i></button>
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteFileFromUploadedFiles('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteFileFromUploadedFiles('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
||||||
|
|||||||
@@ -150,6 +150,11 @@
|
|||||||
<input type="text" id="inputOIDCTokenURL" class="form-control">
|
<input type="text" id="inputOIDCTokenURL" class="form-control">
|
||||||
<small class="text-body-secondary">Token URL from Provider</small>
|
<small class="text-body-secondary">Token URL from Provider</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputOIDCUserInfoURL">User Info URL</label>
|
||||||
|
<input type="text" id="inputOIDCUserInfoURL" class="form-control">
|
||||||
|
<small class="text-body-secondary">Required by some Providers</small>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputOIDCRedirectURL">LubeLogger URL</label>
|
<label for="inputOIDCRedirectURL">LubeLogger URL</label>
|
||||||
<input type="text" id="inputOIDCRedirectURL" class="form-control">
|
<input type="text" id="inputOIDCRedirectURL" class="form-control">
|
||||||
@@ -332,6 +337,7 @@ function generateConfig(){
|
|||||||
ClientSecret: $("#inputOIDCClientSecret").val(),
|
ClientSecret: $("#inputOIDCClientSecret").val(),
|
||||||
AuthURL: $("#inputOIDCAuthURL").val(),
|
AuthURL: $("#inputOIDCAuthURL").val(),
|
||||||
TokenURL: $("#inputOIDCTokenURL").val(),
|
TokenURL: $("#inputOIDCTokenURL").val(),
|
||||||
|
UserInfoURL: $("#inputOIDCUserInfoURL").val(),
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
Scope: $("#inputOIDCScope").val(),
|
Scope: $("#inputOIDCScope").val(),
|
||||||
ValidateState: $("#inputOIDCValidateState").is(":checked"),
|
ValidateState: $("#inputOIDCValidateState").is(":checked"),
|
||||||
@@ -405,6 +411,7 @@ function generateConfig(){
|
|||||||
dockerConfig.push(`OpenIDConfig__ClientSecret="${$('#inputOIDCClientSecret').val()}"`);
|
dockerConfig.push(`OpenIDConfig__ClientSecret="${$('#inputOIDCClientSecret').val()}"`);
|
||||||
dockerConfig.push(`OpenIDConfig__AuthURL="${$('#inputOIDCAuthURL').val()}"`);
|
dockerConfig.push(`OpenIDConfig__AuthURL="${$('#inputOIDCAuthURL').val()}"`);
|
||||||
dockerConfig.push(`OpenIDConfig__TokenURL="${$('#inputOIDCTokenURL').val()}"`);
|
dockerConfig.push(`OpenIDConfig__TokenURL="${$('#inputOIDCTokenURL').val()}"`);
|
||||||
|
dockerConfig.push(`OpenIDConfig__UserInfoURL="${$('#inputOIDCUserInfoURL').val()}"`);
|
||||||
dockerConfig.push(`OpenIDConfig__RedirectURL="${redirectUrl}"`);
|
dockerConfig.push(`OpenIDConfig__RedirectURL="${redirectUrl}"`);
|
||||||
dockerConfig.push(`OpenIDConfig__Scope="${$('#inputOIDCScope').val()}"`);
|
dockerConfig.push(`OpenIDConfig__Scope="${$('#inputOIDCScope').val()}"`);
|
||||||
dockerConfig.push(`OpenIDConfig__ValidateState=${$('#inputOIDCValidateState').is(':checked')}`);
|
dockerConfig.push(`OpenIDConfig__ValidateState=${$('#inputOIDCValidateState').is(':checked')}`);
|
||||||
|
|||||||
@@ -48,12 +48,10 @@ html {
|
|||||||
.swimlane{
|
.swimlane{
|
||||||
height:100%;
|
height:100%;
|
||||||
}
|
}
|
||||||
.swimlane.mid {
|
|
||||||
|
.swimlane:not(:last-child) {
|
||||||
border-right-style: solid;
|
border-right-style: solid;
|
||||||
}
|
}
|
||||||
.swimlane.end {
|
|
||||||
border-left-style: solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.showOnPrint {
|
.showOnPrint {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user