add role check in bulk actions.

This commit is contained in:
DESKTOP-T0O5CDB\DESK-555BD 2025-11-13 07:42:08 -07:00
parent 76d9be7ee5
commit 6065c14f3b
11 changed files with 205 additions and 78 deletions

View File

@ -163,6 +163,11 @@ namespace CarCareTracker.Controllers
foreach (int recordId in editModel.RecordIds) foreach (int recordId in editModel.RecordIds)
{ {
var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId); var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
if (dateIsEdited) if (dateIsEdited)
{ {
existingRecord.Date = editModel.EditRecord.Date; existingRecord.Date = editModel.EditRecord.Date;
@ -205,7 +210,7 @@ namespace CarCareTracker.Controllers
} }
result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord); result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord);
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
} }
} }

View File

@ -186,7 +186,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed($"An error has occurred while generating CSV sample: {ex.Message}")); return Json(OperationResponse.Failed($"An error has occurred while generating CSV sample: {ex.Message}"));
} }
} }
[TypeFilter(typeof(CollaboratorFilter))] [TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.View })]
[HttpGet] [HttpGet]
public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode) public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode)
{ {
@ -408,9 +408,9 @@ namespace CarCareTracker.Controllers
} }
return Json($"/{fileNameToExport}"); return Json($"/{fileNameToExport}");
} }
return Json(false); return Json(OperationResponse.Failed(StaticHelper.GenericErrorMessage));
} }
[TypeFilter(typeof(CollaboratorFilter))] [TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost] [HttpPost]
public IActionResult ImportToVehicleIdFromCsv(int vehicleId, ImportMode mode, string fileName) public IActionResult ImportToVehicleIdFromCsv(int vehicleId, ImportMode mode, string fileName)
{ {

View File

@ -126,7 +126,7 @@ namespace CarCareTracker.Controllers
{ {
if (!_userLogic.UserCanEditVehicle(GetUserID(), vehicleInput.Id, HouseholdPermission.Edit)) if (!_userLogic.UserCanEditVehicle(GetUserID(), vehicleInput.Id, HouseholdPermission.Edit))
{ {
return View("401"); return Json(OperationResponse.Failed("Access Denied"));
} }
} }
//move image from temp folder to images folder. //move image from temp folder to images folder.
@ -143,12 +143,12 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Updated Vehicle {vehicleInput.Year} {vehicleInput.Make} {vehicleInput.Model}({StaticHelper.GetVehicleIdentifier(vehicleInput)})", "vehicle.update", User.Identity.Name, vehicleInput.Id.ToString())); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Updated Vehicle {vehicleInput.Year} {vehicleInput.Make} {vehicleInput.Model}({StaticHelper.GetVehicleIdentifier(vehicleInput)})", "vehicle.update", User.Identity.Name, vehicleInput.Id.ToString()));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Error Saving Vehicle"); _logger.LogError(ex, "Error Saving Vehicle");
return Json(false); return Json(OperationResponse.Failed(StaticHelper.GenericErrorMessage));
} }
} }
[HttpPost] [HttpPost]
@ -206,7 +206,7 @@ namespace CarCareTracker.Controllers
} }
results.Add(result); results.Add(result);
} }
return Json(OperationResponse.Conditional(results.Any() && results.All(x => x), "", StaticHelper.GenericErrorMessage)); return Json(OperationResponse.Conditional(results.Any() && results.All(x => x), string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
[TypeFilter(typeof(StrictCollaboratorFilter), Arguments = new object[] { true, true })] [TypeFilter(typeof(StrictCollaboratorFilter), Arguments = new object[] { true, true })]
@ -631,6 +631,11 @@ namespace CarCareTracker.Controllers
genericRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId); genericRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
break; break;
} }
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), genericRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
//save //save
switch (destination) switch (destination)
{ {
@ -681,6 +686,11 @@ namespace CarCareTracker.Controllers
genericRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId); genericRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
break; break;
} }
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), genericRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
//save //save
switch (destination) switch (destination)
{ {
@ -715,7 +725,7 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Moved multiple {source.ToString()} to {destination.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.move", User.Identity.Name, string.Empty)); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Moved multiple {source.ToString()} to {destination.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.move", User.Identity.Name, string.Empty));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
public IActionResult DeleteRecords(List<int> recordIds, ImportMode importMode) public IActionResult DeleteRecords(List<int> recordIds, ImportMode importMode)
{ {
@ -762,8 +772,8 @@ namespace CarCareTracker.Controllers
} }
return Json(result); return Json(result);
} }
[TypeFilter(typeof(CollaboratorFilter))]
[HttpPost] [HttpPost]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] {false, true, HouseholdPermission.Edit})]
public IActionResult AdjustRecordsOdometer(List<int> recordIds, int vehicleId, ImportMode importMode) public IActionResult AdjustRecordsOdometer(List<int> recordIds, int vehicleId, ImportMode importMode)
{ {
bool result = false; bool result = false;
@ -819,7 +829,7 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Adjusted odometer for multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.odometer.adjust", User.Identity.Name, string.Empty)); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Adjusted odometer for multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.odometer.adjust", User.Identity.Name, string.Empty));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
public IActionResult DuplicateRecords(List<int> recordIds, ImportMode importMode) public IActionResult DuplicateRecords(List<int> recordIds, ImportMode importMode)
@ -832,6 +842,11 @@ namespace CarCareTracker.Controllers
case ImportMode.ServiceRecord: case ImportMode.ServiceRecord:
{ {
var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId); var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.RequisitionHistory = new List<SupplyUsageHistory>(); existingRecord.RequisitionHistory = new List<SupplyUsageHistory>();
result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(existingRecord); result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(existingRecord);
@ -840,6 +855,11 @@ namespace CarCareTracker.Controllers
case ImportMode.RepairRecord: case ImportMode.RepairRecord:
{ {
var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId); var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.RequisitionHistory = new List<SupplyUsageHistory>(); existingRecord.RequisitionHistory = new List<SupplyUsageHistory>();
result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(existingRecord); result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(existingRecord);
@ -848,6 +868,11 @@ namespace CarCareTracker.Controllers
case ImportMode.UpgradeRecord: case ImportMode.UpgradeRecord:
{ {
var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId); var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.RequisitionHistory = new List<SupplyUsageHistory>(); existingRecord.RequisitionHistory = new List<SupplyUsageHistory>();
result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(existingRecord); result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(existingRecord);
@ -856,6 +881,11 @@ namespace CarCareTracker.Controllers
case ImportMode.GasRecord: case ImportMode.GasRecord:
{ {
var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId); var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord); result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord);
} }
@ -863,6 +893,11 @@ namespace CarCareTracker.Controllers
case ImportMode.TaxRecord: case ImportMode.TaxRecord:
{ {
var existingRecord = _taxRecordDataAccess.GetTaxRecordById(recordId); var existingRecord = _taxRecordDataAccess.GetTaxRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
result = _taxRecordDataAccess.SaveTaxRecordToVehicle(existingRecord); result = _taxRecordDataAccess.SaveTaxRecordToVehicle(existingRecord);
} }
@ -870,6 +905,11 @@ namespace CarCareTracker.Controllers
case ImportMode.SupplyRecord: case ImportMode.SupplyRecord:
{ {
var existingRecord = _supplyRecordDataAccess.GetSupplyRecordById(recordId); var existingRecord = _supplyRecordDataAccess.GetSupplyRecordById(recordId);
//security check if not shop supply
if (existingRecord.VehicleId != default && !_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.RequisitionHistory = new List<SupplyUsageHistory>(); existingRecord.RequisitionHistory = new List<SupplyUsageHistory>();
result = _supplyRecordDataAccess.SaveSupplyRecordToVehicle(existingRecord); result = _supplyRecordDataAccess.SaveSupplyRecordToVehicle(existingRecord);
@ -878,6 +918,11 @@ namespace CarCareTracker.Controllers
case ImportMode.NoteRecord: case ImportMode.NoteRecord:
{ {
var existingRecord = _noteDataAccess.GetNoteById(recordId); var existingRecord = _noteDataAccess.GetNoteById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
result = _noteDataAccess.SaveNoteToVehicle(existingRecord); result = _noteDataAccess.SaveNoteToVehicle(existingRecord);
} }
@ -885,6 +930,11 @@ namespace CarCareTracker.Controllers
case ImportMode.OdometerRecord: case ImportMode.OdometerRecord:
{ {
var existingRecord = _odometerRecordDataAccess.GetOdometerRecordById(recordId); var existingRecord = _odometerRecordDataAccess.GetOdometerRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(existingRecord); result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(existingRecord);
} }
@ -892,6 +942,11 @@ namespace CarCareTracker.Controllers
case ImportMode.ReminderRecord: case ImportMode.ReminderRecord:
{ {
var existingRecord = _reminderRecordDataAccess.GetReminderRecordById(recordId); var existingRecord = _reminderRecordDataAccess.GetReminderRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
result = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingRecord); result = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingRecord);
} }
@ -899,6 +954,11 @@ namespace CarCareTracker.Controllers
case ImportMode.PlanRecord: case ImportMode.PlanRecord:
{ {
var existingRecord = _planRecordDataAccess.GetPlanRecordById(recordId); var existingRecord = _planRecordDataAccess.GetPlanRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.ReminderRecordId = default; existingRecord.ReminderRecordId = default;
existingRecord.RequisitionHistory = new List<SupplyUsageHistory>(); existingRecord.RequisitionHistory = new List<SupplyUsageHistory>();
@ -908,6 +968,11 @@ namespace CarCareTracker.Controllers
case ImportMode.InspectionRecord: case ImportMode.InspectionRecord:
{ {
var existingRecord = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(recordId); var existingRecord = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
existingRecord.Id = default; existingRecord.Id = default;
existingRecord.ReminderRecordId = new List<int>(); existingRecord.ReminderRecordId = new List<int>();
result = _inspectionRecordTemplateDataAccess.SaveInspectionReportTemplateToVehicle(existingRecord); result = _inspectionRecordTemplateDataAccess.SaveInspectionReportTemplateToVehicle(existingRecord);
@ -919,9 +984,10 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Duplicated multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.duplicate", User.Identity.Name, string.Empty)); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Duplicated multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.duplicate", User.Identity.Name, string.Empty));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { true, true, HouseholdPermission.Edit })]
public IActionResult DuplicateRecordsToOtherVehicles(List<int> recordIds, List<int> vehicleIds, ImportMode importMode) public IActionResult DuplicateRecordsToOtherVehicles(List<int> recordIds, List<int> vehicleIds, ImportMode importMode)
{ {
bool result = false; bool result = false;
@ -1066,7 +1132,7 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Duplicated multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)} - to Vehicle Ids: {string.Join(",", vehicleIds)}", "bulk.duplicate.to.vehicles", User.Identity.Name, string.Join(",", vehicleIds))); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Duplicated multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)} - to Vehicle Ids: {string.Join(",", vehicleIds)}", "bulk.duplicate.to.vehicles", User.Identity.Name, string.Join(",", vehicleIds)));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
public IActionResult BulkCreateOdometerRecords(List<int> recordIds, ImportMode importMode) public IActionResult BulkCreateOdometerRecords(List<int> recordIds, ImportMode importMode)
@ -1079,6 +1145,11 @@ namespace CarCareTracker.Controllers
case ImportMode.ServiceRecord: case ImportMode.ServiceRecord:
{ {
var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId); var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
{ {
Date = existingRecord.Date, Date = existingRecord.Date,
@ -1092,6 +1163,11 @@ namespace CarCareTracker.Controllers
case ImportMode.RepairRecord: case ImportMode.RepairRecord:
{ {
var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId); var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
{ {
Date = existingRecord.Date, Date = existingRecord.Date,
@ -1105,6 +1181,11 @@ namespace CarCareTracker.Controllers
case ImportMode.UpgradeRecord: case ImportMode.UpgradeRecord:
{ {
var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId); var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
{ {
Date = existingRecord.Date, Date = existingRecord.Date,
@ -1118,6 +1199,11 @@ namespace CarCareTracker.Controllers
case ImportMode.GasRecord: case ImportMode.GasRecord:
{ {
var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId); var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord result = _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
{ {
Date = existingRecord.Date, Date = existingRecord.Date,
@ -1134,7 +1220,7 @@ namespace CarCareTracker.Controllers
{ {
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Created Odometer Records based on {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.odometer.insert", User.Identity.Name, string.Empty)); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.Generic($"Created Odometer Records based on {importMode.ToString()} - Ids: {string.Join(",", recordIds)}", "bulk.odometer.insert", User.Identity.Name, string.Empty));
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
public IActionResult GetGenericRecordModal(List<int> recordIds, ImportMode dataType) public IActionResult GetGenericRecordModal(List<int> recordIds, ImportMode dataType)
@ -1169,6 +1255,11 @@ namespace CarCareTracker.Controllers
case ImportMode.ServiceRecord: case ImportMode.ServiceRecord:
{ {
var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId); var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
if (dateIsEdited) if (dateIsEdited)
{ {
existingRecord.Date = genericRecordEditModel.EditRecord.Date; existingRecord.Date = genericRecordEditModel.EditRecord.Date;
@ -1215,6 +1306,11 @@ namespace CarCareTracker.Controllers
case ImportMode.RepairRecord: case ImportMode.RepairRecord:
{ {
var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId); var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
if (dateIsEdited) if (dateIsEdited)
{ {
existingRecord.Date = genericRecordEditModel.EditRecord.Date; existingRecord.Date = genericRecordEditModel.EditRecord.Date;
@ -1261,6 +1357,11 @@ namespace CarCareTracker.Controllers
case ImportMode.UpgradeRecord: case ImportMode.UpgradeRecord:
{ {
var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId); var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
//security check
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit))
{
return Json(OperationResponse.Failed("Access Denied"));
}
if (dateIsEdited) if (dateIsEdited)
{ {
existingRecord.Date = genericRecordEditModel.EditRecord.Date; existingRecord.Date = genericRecordEditModel.EditRecord.Date;
@ -1306,9 +1407,10 @@ namespace CarCareTracker.Controllers
break; break;
} }
} }
return Json(result); return Json(OperationResponse.Conditional(result, string.Empty, StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.View })]
public IActionResult PrintRecordStickers(int vehicleId, List<int> recordIds, ImportMode importMode) public IActionResult PrintRecordStickers(int vehicleId, List<int> recordIds, ImportMode importMode)
{ {
bool result = false; bool result = false;
@ -1475,7 +1577,7 @@ namespace CarCareTracker.Controllers
{ {
return PartialView("_Stickers", stickerViewModel); return PartialView("_Stickers", stickerViewModel);
} }
return Json(result); return Json(OperationResponse.Failed(StaticHelper.GenericErrorMessage));
} }
[HttpPost] [HttpPost]
public IActionResult SaveUserColumnPreferences(UserColumnPreference columnPreference) public IActionResult SaveUserColumnPreferences(UserColumnPreference columnPreference)

View File

@ -11,42 +11,58 @@ namespace CarCareTracker.Filter
{ {
private readonly IUserLogic _userLogic; private readonly IUserLogic _userLogic;
private readonly IConfigHelper _config; private readonly IConfigHelper _config;
public CollaboratorFilter(IUserLogic userLogic, IConfigHelper config) { private readonly bool _multiple;
private readonly bool _jsonResponse;
private readonly HouseholdPermission _permission;
public CollaboratorFilter(IUserLogic userLogic, IConfigHelper config, bool? multiple = false, bool? jsonResponse = false, HouseholdPermission? permission = HouseholdPermission.View) {
_userLogic = userLogic; _userLogic = userLogic;
_config = config; _config = config;
_multiple = multiple ?? false; ;
_jsonResponse = jsonResponse ?? false;
_permission = permission ?? HouseholdPermission.View;
} }
public override void OnActionExecuting(ActionExecutingContext filterContext) public override void OnActionExecuting(ActionExecutingContext filterContext)
{ {
if (!filterContext.HttpContext.User.IsInRole(nameof(UserData.IsRootUser))) if (!filterContext.HttpContext.User.IsInRole(nameof(UserData.IsRootUser)))
{ {
if (filterContext.ActionArguments.ContainsKey("vehicleId")) List<int> vehicleIds = new List<int>();
if (!_multiple && filterContext.ActionArguments.ContainsKey("vehicleId"))
{ {
var vehicleId = int.Parse(filterContext.ActionArguments["vehicleId"].ToString()); vehicleIds.Add(int.Parse(filterContext.ActionArguments["vehicleId"].ToString()));
if (vehicleId != default) }
else if (_multiple && filterContext.ActionArguments.ContainsKey("vehicleIds"))
{
vehicleIds.AddRange(filterContext.ActionArguments["vehicleIds"] as List<int>);
}
if (vehicleIds.Any())
{
foreach(int vehicleId in vehicleIds)
{ {
var userId = int.Parse(filterContext.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)); if (vehicleId != default)
if (!_userLogic.UserCanEditVehicle(userId, vehicleId, HouseholdPermission.View))
{ {
filterContext.Result = new RedirectResult("/Error/Unauthorized"); var userId = int.Parse(filterContext.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
if (!_userLogic.UserCanEditVehicle(userId, vehicleId, _permission))
{
filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");
}
} }
} else
else
{
var shopSupplyEndpoints = new List<string> { "ImportToVehicleIdFromCsv", "GetSupplyRecordsByVehicleId", "ExportFromVehicleToCsv" };
if (shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
{ {
//user trying to access shop supplies but shop supplies is not enabled by root user. if (StaticHelper.IsShopSupplyEndpoint(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
filterContext.Result = new RedirectResult("/Error/Unauthorized"); {
} //user trying to access shop supplies but shop supplies is not enabled by root user.
else if (!shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString())) filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");
{ }
//user trying to access any other endpoints using 0 as vehicle id. else if (!StaticHelper.IsShopSupplyEndpoint(filterContext.RouteData.Values["action"].ToString()))
filterContext.Result = new RedirectResult("/Error/Unauthorized"); {
//user trying to access any other endpoints using 0 as vehicle id.
filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");
}
} }
} }
} else } else
{ {
filterContext.Result = new RedirectResult("/Error/Unauthorized"); filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");
} }
} }
} }

View File

@ -47,13 +47,12 @@ namespace CarCareTracker.Filter
} }
else else
{ {
var shopSupplyEndpoints = new List<string> { "ImportToVehicleIdFromCsv", "GetSupplyRecordsByVehicleId", "ExportFromVehicleToCsv" }; if (StaticHelper.IsShopSupplyEndpoint(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
if (shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
{ {
//user trying to access shop supplies but shop supplies is not enabled by root user. //user trying to access shop supplies but shop supplies is not enabled by root user.
filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized"); filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");
} }
else if (!shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString())) else if (!StaticHelper.IsShopSupplyEndpoint(filterContext.RouteData.Values["action"].ToString()))
{ {
//user trying to access any other endpoints using 0 as vehicle id. //user trying to access any other endpoints using 0 as vehicle id.
filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized"); filterContext.Result = _jsonResponse ? new JsonResult(OperationResponse.Failed("Access Denied")) : new RedirectResult("/Error/Unauthorized");

View File

@ -935,5 +935,10 @@ namespace CarCareTracker.Helper
return Convert.ToDecimal(goodNormalizedStep * stepPower); return Convert.ToDecimal(goodNormalizedStep * stepPower);
} }
public static bool IsShopSupplyEndpoint(string endpoint)
{
var shopSupplyEndpoints = new List<string> { "ImportToVehicleIdFromCsv", "GetSupplyRecordsByVehicleId", "ExportFromVehicleToCsv", "DuplicateRecordsToOtherVehicles", "PrintRecordStickers" };
return shopSupplyEndpoints.Contains(endpoint);
}
} }
} }

View File

@ -144,26 +144,19 @@ namespace CarCareTracker.Logic
} }
public bool UserCanEditVehicle(int userId, int vehicleId, HouseholdPermission permission) public bool UserCanEditVehicle(int userId, int vehicleId, HouseholdPermission permission)
{ {
if (userId == -1) //check if user is full collaborator or root user
if (UserCanDirectlyEditVehicle(userId, vehicleId))
{ {
return true; return true;
} }
List<int> userIds = new List<int> { userId }; //user is not a full collaborator, check households
List<int> userIds = new List<int>();
var userHouseholds = _userHouseholdData.GetUserHouseholdByChildUserId(userId); var userHouseholds = _userHouseholdData.GetUserHouseholdByChildUserId(userId);
if (userHouseholds.Any()) foreach (UserHousehold userHousehold in userHouseholds)
{ {
//add parent's user ids //check if the direct parents have access to the vehicle
userIds.AddRange(userHouseholds.Select(x => x.Id.ParentUserId)); var userAccess = _userAccess.GetUserAccessByVehicleAndUserId(userHousehold.Id.ParentUserId, vehicleId);
} if (userAccess != null && userAccess.Id.UserId == userHousehold.Id.ParentUserId && userAccess.Id.VehicleId == vehicleId)
foreach (int userIdToCheck in userIds)
{
var userAccess = _userAccess.GetUserAccessByVehicleAndUserId(userIdToCheck, vehicleId);
if (userAccess != null && userAccess.Id.UserId == userId && userAccess.Id.VehicleId == vehicleId)
{
//full collaborator, not through household
return true;
}
else if (userAccess != null && userAccess.Id.UserId == userIdToCheck && userAccess.Id.VehicleId == vehicleId)
{ {
//every member in a household has permission to view vehicles //every member in a household has permission to view vehicles
if (permission == HouseholdPermission.View) if (permission == HouseholdPermission.View)
@ -171,7 +164,7 @@ namespace CarCareTracker.Logic
return true; return true;
} else } else
{ {
return userHouseholds.First(x => x.Id.ParentUserId == userIdToCheck && x.Id.ChildUserId == userId).Permissions.Contains(permission); return userHousehold.Permissions.Contains(permission);
} }
} }
} }

View File

@ -45,7 +45,10 @@
sloader.show(); sloader.show();
$.post('/Vehicle/ImportToVehicleIdFromCsv', { vehicleId: vehicleId, mode: mode, fileName: uploadedFile }, function (data) { $.post('/Vehicle/ImportToVehicleIdFromCsv', { vehicleId: vehicleId, mode: mode, fileName: uploadedFile }, function (data) {
sloader.hide(); sloader.hide();
if (data) { if (isOperationResponse(data)) {
return;
}
else if (data) {
successToast("Data Imported Successfully"); successToast("Data Imported Successfully");
hideBulkImportModal(); hideBulkImportModal();
if (mode == "GasRecord") { if (mode == "GasRecord") {

View File

@ -486,13 +486,13 @@ function saveMultipleGasRecordsToVehicle() {
} }
} }
$.post('/Vehicle/SaveMultipleGasRecords', { editModel: formValues }, function (data) { $.post('/Vehicle/SaveMultipleGasRecords', { editModel: formValues }, function (data) {
if (data) { if (data.success) {
successToast("Gas Records Updated"); successToast("Gas Records Updated");
hideAddGasRecordModal(); hideAddGasRecordModal();
saveScrollPosition(); saveScrollPosition();
getVehicleGasRecords(GetVehicleId().vehicleId); getVehicleGasRecords(GetVehicleId().vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}) })
} }

View File

@ -178,7 +178,7 @@ function saveVehicle(isEdit) {
dashboardMetrics: vehicleDashboardMetrics, dashboardMetrics: vehicleDashboardMetrics,
vehicleIdentifier: vehicleIdentifier vehicleIdentifier: vehicleIdentifier
}, function (data) { }, function (data) {
if (data) { if (data.success) {
if (!isEdit) { if (!isEdit) {
successToast("Vehicle Added"); successToast("Vehicle Added");
hideAddVehicleModal(); hideAddVehicleModal();
@ -190,7 +190,7 @@ function saveVehicle(isEdit) {
viewVehicle(vehicleId); viewVehicle(vehicleId);
} }
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} }
@ -756,7 +756,10 @@ function printTabStickers(ids, source) {
recordIds: ids, recordIds: ids,
importMode: source importMode: source
}, function (data) { }, function (data) {
if (data) { if (isOperationResponse(data)) {
return;
}
else if (data) {
printContainer(data); printContainer(data);
} }
}) })
@ -764,9 +767,10 @@ function printTabStickers(ids, source) {
function exportVehicleData(mode) { function exportVehicleData(mode) {
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
$.get('/Vehicle/ExportFromVehicleToCsv', { vehicleId: vehicleId, mode: mode }, function (data) { $.get('/Vehicle/ExportFromVehicleToCsv', { vehicleId: vehicleId, mode: mode }, function (data) {
if (!data) { if (isOperationResponse(data)) {
errorToast(genericErrorMessage()); return;
} else { }
else if (data) {
window.location.href = data; window.location.href = data;
} }
}); });
@ -857,12 +861,12 @@ function moveRecords(ids, source, dest) {
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/MoveRecords', { recordIds: ids, source: source, destination: dest }, function (data) { $.post('/Vehicle/MoveRecords', { recordIds: ids, source: source, destination: dest }, function (data) {
if (data) { if (data.success) {
successToast(`${ids.length} Record(s) Moved`); successToast(`${ids.length} Record(s) Moved`);
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId); refreshDataCallBack(vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} else { } else {
@ -1005,12 +1009,12 @@ function duplicateRecords(ids, source) {
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/DuplicateRecords', { recordIds: ids, importMode: source }, function (data) { $.post('/Vehicle/DuplicateRecords', { recordIds: ids, importMode: source }, function (data) {
if (data) { if (data.success) {
successToast(`${ids.length} Record(s) Duplicated`); successToast(`${ids.length} Record(s) Duplicated`);
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId); refreshDataCallBack(vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} else { } else {
@ -1091,10 +1095,10 @@ function duplicateRecordsToOtherVehicles(ids, source) {
}).then(function (result) { }).then(function (result) {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/DuplicateRecordsToOtherVehicles', { recordIds: ids, vehicleIds: result.value.selectedVehicleData.ids, importMode: source}, function (data) { $.post('/Vehicle/DuplicateRecordsToOtherVehicles', { recordIds: ids, vehicleIds: result.value.selectedVehicleData.ids, importMode: source}, function (data) {
if (data) { if (data.success) {
successToast(`${ids.length} Record(s) Duplicated`); successToast(`${ids.length} Record(s) Duplicated`);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} }
@ -1140,12 +1144,12 @@ function insertOdometer(ids, source) {
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/BulkCreateOdometerRecords', { recordIds: ids, importMode: source }, function (data) { $.post('/Vehicle/BulkCreateOdometerRecords', { recordIds: ids, importMode: source }, function (data) {
if (data) { if (data.success) {
successToast(`${ids.length} Odometer Record(s) Created`); successToast(`${ids.length} Odometer Record(s) Created`);
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId); refreshDataCallBack(vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} else { } else {

View File

@ -306,13 +306,13 @@ function moveRecord(recordId, source, dest) {
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/MoveRecord', { recordId: recordId, source: source, destination: dest }, function (data) { $.post('/Vehicle/MoveRecord', { recordId: recordId, source: source, destination: dest }, function (data) {
if (data) { if (data.success) {
hideModalCallBack(); hideModalCallBack();
successToast("Record Moved"); successToast("Record Moved");
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId); refreshDataCallBack(vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} else { } else {
@ -414,12 +414,12 @@ function saveGenericRecord() {
} }
//save to db. //save to db.
$.post('/Vehicle/EditMultipleRecords', { genericRecordEditModel: formValues }, function (data) { $.post('/Vehicle/EditMultipleRecords', { genericRecordEditModel: formValues }, function (data) {
if (data) { if (data.success) {
successToast(formValues.recordIds.length > 1 ? "Records Updated" : "Record Updated."); successToast(formValues.recordIds.length > 1 ? "Records Updated" : "Record Updated.");
hideGenericRecordModal(); hideGenericRecordModal();
refreshDataCallBack(GetVehicleId().vehicleId); refreshDataCallBack(GetVehicleId().vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}) })
} }
@ -563,12 +563,12 @@ function adjustRecordsOdometer(ids, source) {
if (result.isConfirmed) { if (result.isConfirmed) {
saveScrollPosition(); saveScrollPosition();
$.post('/Vehicle/AdjustRecordsOdometer', { recordIds: ids, vehicleId: GetVehicleId().vehicleId, importMode: source }, function (data) { $.post('/Vehicle/AdjustRecordsOdometer', { recordIds: ids, vehicleId: GetVehicleId().vehicleId, importMode: source }, function (data) {
if (data) { if (data.success) {
successToast(`${ids.length} Record(s) Updated`); successToast(`${ids.length} Record(s) Updated`);
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId); refreshDataCallBack(vehicleId);
} else { } else {
errorToast(genericErrorMessage()); errorToast(data.message);
} }
}); });
} else { } else {