add api key filter

This commit is contained in:
DESKTOP-T0O5CDB\DESK-555BD 2026-01-24 20:26:49 -07:00
parent 5904461f94
commit 7ba06e01e4
13 changed files with 101 additions and 0 deletions

View File

@ -78,11 +78,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/equipmentrecords/add")]
[Consumes("application/json")]
public IActionResult AddEquipmentRecordJson(int vehicleId, [FromBody] EquipmentRecordExportModel input) => AddEquipmentRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/equipmentrecords/add")]
@ -129,6 +131,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/equipmentrecords/delete")]
public IActionResult DeleteEquipmentRecord(int id)
@ -163,10 +166,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Equipment Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/equipmentrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateEquipmentRecordJson([FromBody] EquipmentRecordExportModel input) => UpdateEquipmentRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/equipmentrecords/update")]
public IActionResult UpdateEquipmentRecord(EquipmentRecordExportModel input)

View File

@ -121,11 +121,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/gasrecords/add")]
[Consumes("application/json")]
public IActionResult AddGasRecordJson(int vehicleId, [FromBody] GasRecordExportModel input) => AddGasRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/gasrecords/add")]
@ -193,6 +195,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/gasrecords/delete")]
public IActionResult DeleteGasRecord(int id)
@ -216,10 +219,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Gas Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/gasrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateGasRecordJson([FromBody] GasRecordExportModel input) => UpdateGasRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/gasrecords/update")]
public IActionResult UpdateGasRecord(GasRecordExportModel input)

View File

@ -21,6 +21,7 @@ namespace CarCareTracker.Controllers
var result = _vehicleLogic.GetMaxMileage(vehicleId);
return Json(result);
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/odometerrecords/recalculate")]
@ -123,11 +124,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/odometerrecords/add")]
[Consumes("application/json")]
public IActionResult AddOdometerRecordJson(int vehicleId, [FromBody] OdometerRecordExportModel input) => AddOdometerRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/odometerrecords/add")]
@ -207,6 +210,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/odometerrecords/delete")]
public IActionResult DeleteOdometerRecord(int id)
@ -230,10 +234,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Odometer Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/odometerrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateOdometerRecordJson([FromBody] OdometerRecordExportModel input) => UpdateOdometerRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/odometerrecords/update")]
public IActionResult UpdateOdometerRecord(OdometerRecordExportModel input)

View File

@ -105,11 +105,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/planrecords/add")]
[Consumes("application/json")]
public IActionResult AddPlanRecordJson(int vehicleId, [FromBody] PlanRecordExportModel input) => AddPlanRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/planrecords/add")]
@ -182,6 +184,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/planrecords/delete")]
public IActionResult DeletePlanRecord(int id)
@ -210,10 +213,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Plan Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/planrecords/update")]
[Consumes("application/json")]
public IActionResult UpdatePlanRecordJson([FromBody] PlanRecordExportModel input) => UpdatePlanRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/planrecords/update")]
public IActionResult UpdatePlanRecord(PlanRecordExportModel input)

View File

@ -88,11 +88,13 @@ namespace CarCareTracker.Controllers
return Json(results);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/reminders/add")]
[Consumes("application/json")]
public IActionResult AddReminderRecordJson(int vehicleId, [FromBody] ReminderExportModel input) => AddReminderRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/reminders/add")]
@ -162,10 +164,12 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/reminders/update")]
[Consumes("application/json")]
public IActionResult UpdateReminderRecordJson([FromBody] ReminderExportModel input) => UpdateReminderRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/reminders/update")]
public IActionResult UpdateReminderRecord(ReminderExportModel input)
@ -242,6 +246,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/reminders/delete")]
public IActionResult DeleteReminderRecord(int id)

View File

@ -89,11 +89,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/repairrecords/add")]
[Consumes("application/json")]
public IActionResult AddRepairRecordJson(int vehicleId, [FromBody] GenericRecordExportModel input) => AddRepairRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/repairrecords/add")]
@ -157,6 +159,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/repairrecords/delete")]
public IActionResult DeleteRepairRecord(int id)
@ -185,10 +188,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Repair Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/repairrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateRepairRecordJson([FromBody] GenericRecordExportModel input) => UpdateRepairRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/repairrecords/update")]
public IActionResult UpdateRepairRecord(GenericRecordExportModel input)

View File

@ -89,11 +89,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/servicerecords/add")]
[Consumes("application/json")]
public IActionResult AddServiceRecordJson(int vehicleId, [FromBody] GenericRecordExportModel input) => AddServiceRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/servicerecords/add")]
@ -156,6 +158,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/servicerecords/delete")]
public IActionResult DeleteServiceRecord(int id)
@ -184,10 +187,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Service Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/servicerecords/update")]
[Consumes("application/json")]
public IActionResult UpdateServiceRecordJson([FromBody] GenericRecordExportModel input) => UpdateServiceRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/servicerecords/update")]
public IActionResult UpdateServiceRecord(GenericRecordExportModel input)

View File

@ -121,11 +121,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/supplyrecords/add")]
[Consumes("application/json")]
public IActionResult AddSupplyRecordJson(int vehicleId, [FromBody] SupplyRecordExportModel input) => AddSupplyRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/supplyrecords/add")]
@ -178,6 +180,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/supplyrecords/delete")]
public IActionResult DeleteSupplyRecord(int id)
@ -211,10 +214,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Supply Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/supplyrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateSupplyRecordJson([FromBody] SupplyRecordExportModel input) => UpdateSupplyRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/supplyrecords/update")]
public IActionResult UpdateSupplyRecord(SupplyRecordExportModel input)

View File

@ -125,11 +125,13 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed($"No Recurring Taxes Updated Due To Error: {ex.Message}"));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/taxrecords/add")]
[Consumes("application/json")]
public IActionResult AddTaxRecordJson(int vehicleId, [FromBody] TaxRecordExportModel input) => AddTaxRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/taxrecords/add")]
@ -179,6 +181,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/taxrecords/delete")]
public IActionResult DeleteTaxRecord(int id)
@ -202,10 +205,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Tax Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/taxrecords/update")]
[Consumes("application/json")]
public IActionResult UpdateTaxRecordJson([FromBody] TaxRecordExportModel input) => UpdateTaxRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/taxrecords/update")]
public IActionResult UpdateTaxRecord(TaxRecordExportModel input)

View File

@ -89,11 +89,13 @@ namespace CarCareTracker.Controllers
return Json(result);
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/upgraderecords/add")]
[Consumes("application/json")]
public IActionResult AddUpgradeRecordJson(int vehicleId, [FromBody] GenericRecordExportModel input) => AddUpgradeRecord(vehicleId, input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })]
[HttpPost]
[Route("/api/vehicle/upgraderecords/add")]
@ -156,6 +158,7 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })]
[HttpDelete]
[Route("/api/vehicle/upgraderecords/delete")]
public IActionResult DeleteUpgradeRecord(int id)
@ -184,10 +187,12 @@ namespace CarCareTracker.Controllers
}
return Json(OperationResponse.Conditional(result, "Upgrade Record Deleted"));
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/upgraderecords/update")]
[Consumes("application/json")]
public IActionResult UpdateUpgradeRecordJson([FromBody] GenericRecordExportModel input) => UpdateUpgradeRecord(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicle/upgraderecords/update")]
public IActionResult UpdateUpgradeRecord(GenericRecordExportModel input)

View File

@ -317,10 +317,12 @@ namespace CarCareTracker.Controllers
return Json(OperationResponse.Failed(ex.Message));
}
}
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicles/update")]
[Consumes("application/json")]
public IActionResult UpdateVehicleJson([FromBody] VehicleImportModel input) => UpdateVehicle(input);
[TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })]
[HttpPut]
[Route("/api/vehicles/update")]
public IActionResult UpdateVehicle(VehicleImportModel input)

37
Filter/APIKeyFilter.cs Normal file
View File

@ -0,0 +1,37 @@
using CarCareTracker.Logic;
using CarCareTracker.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace CarCareTracker.Filter
{
public class APIKeyFilter: ActionFilterAttribute
{
private readonly IUserLogic _userLogic;
private readonly HouseholdPermission _permission;
public APIKeyFilter(IUserLogic userLogic, HouseholdPermission? permission = HouseholdPermission.View) {
_userLogic = userLogic;
_permission = permission ?? HouseholdPermission.View;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User.IsInRole("APIKeyAuth"))
{
var apikey_header = filterContext.HttpContext.Request.Headers["x-api-key"];
if (string.IsNullOrWhiteSpace(apikey_header))
{
apikey_header = filterContext.HttpContext.Request.Query["apiKey"];
}
if (!string.IsNullOrWhiteSpace(apikey_header))
{
var permissions = _userLogic.GetAPIKeyPermissions(apikey_header);
if (!permissions.Contains(_permission))
{
filterContext.Result = new JsonResult(OperationResponse.Failed("Access Denied"));
filterContext.HttpContext.Response.StatusCode = 401;
}
}
}
}
}
}

View File

@ -25,6 +25,7 @@ namespace CarCareTracker.Logic
bool DeleteAllHouseholdByChildUserId(int childUserId);
OperationResponse CreateAPIKey(int userId, string keyName, List<HouseholdPermission> permisions);
List<APIKey> GetAPIKeysByUserId(int userId);
List<HouseholdPermission> GetAPIKeyPermissions(string apiKey);
bool DeleteAPIKeyByKeyIdAndUserId(int keyId, int userId);
bool DeleteAllAPIKeysByUserId(int userId);
}
@ -325,6 +326,16 @@ namespace CarCareTracker.Logic
var result = _apiKeyData.GetAPIKeyRecordsByUserId(userId);
return result;
}
public List<HouseholdPermission> GetAPIKeyPermissions(string apiKey)
{
var hashedKey = StaticHelper.GetHash(apiKey);
var existingKey = _apiKeyData.GetAPIKeyByKey(hashedKey);
if (existingKey.Id != default)
{
return existingKey.Permissions;
}
return new List<HouseholdPermission>();
}
public bool DeleteAPIKeyByKeyIdAndUserId(int keyId, int userId)
{
var existingKey = _apiKeyData.GetAPIKeyById(keyId);