oi-metrology/Archive/ApiControllers/InboundController.cs
2022-07-26 09:34:09 -07:00

169 lines
5.5 KiB
C#

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OI.Metrology.Archive.ApiContollers;
[ApiController]
public class InboundController : ControllerBase
{
private IConfiguration Config { get; }
private ILogger Logger { get; }
protected IMetrologyRepo _Repo;
protected IAttachmentsService _AttachmentService;
protected IInboundDataService _InboundDataService;
public InboundController(IConfiguration config, ILogger<InboundController> logger, IMetrologyRepo repo, IInboundDataService inboundDataService, IAttachmentsService attachmentService)
{
Config = config;
Logger = logger;
_Repo = repo;
_InboundDataService = inboundDataService;
_AttachmentService = attachmentService;
}
// this class represents the API response back to the client
public class DataResponse
{
public bool Success { get; set; }
public long HeaderID { get; set; }
public List<string> Errors { get; set; }
public List<string> Warnings { get; set; }
}
// this is the main endpoint, it accepts a JSON message that contains both the header and data records together
// tooltype is the ToolTypeName column from the ToolType table
// JToken is how you can accept a JSON message without deserialization.
// Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string.
[HttpPost("/api/inbound/{tooltype}")]
public IActionResult Data(string tooltype, [FromBody] JToken jsonbody)
{
DataResponse r = new()
{
Success = false,
HeaderID = -1,
Errors = new List<string>(),
Warnings = new List<string>()
};
if (!IsIPAddressAllowed())
{
Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
r.Errors.Add("Remote IP is not on allowed list");
return Unauthorized(r);
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
if (toolType == null)
{
r.Errors.Add("Invalid tool type: " + tooltype);
return BadRequest(r);
}
// get metadata
List<ToolTypeMetadata> metaData = _Repo.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
if (metaData == null)
{
r.Errors.Add("Invalid metadata for tool type: " + tooltype);
return BadRequest(r);
}
// validate fields
if (jsonbody != null)
_InboundDataService.ValidateJSONFields(jsonbody, 0, metaData, r.Errors, r.Warnings);
else
r.Errors.Add("Invalid json");
if (r.Errors.Count == 0)
{
try
{
r.HeaderID = _InboundDataService.DoSQLInsert(jsonbody, toolType, metaData);
r.Success = r.HeaderID > 0;
}
catch (Exception ex)
{
r.Errors.Add(ex.Message);
}
return Ok(r);
}
else
{
return BadRequest(r);
}
}
// this is the endpoint for attaching a field. It is not JSON, it is form-data/multipart like an HTML form because that's the normal way.
// header ID is the ID value from the Header table
// datauniqueid is the Title value from the Data/Detail table
[HttpPost("/api/inbound/{tooltype}/attachment")]
public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
{
if (!IsIPAddressAllowed())
{
Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
return Unauthorized("Remote IP is not on allowed list");
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
if (toolType == null)
return BadRequest($"Invalid tool type: {tooltype}");
if (Request.Form == null)
return BadRequest($"Invalid form");
if (Request.Form.Files.Count != 1)
return BadRequest($"Invalid file count");
string filename = System.IO.Path.GetFileName(Request.Form.Files[0].FileName);
if (string.IsNullOrWhiteSpace(filename))
return BadRequest("Empty filename");
if (filename.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) >= 0)
return BadRequest("Invalid filename");
_AttachmentService.SaveAttachment(toolType, headerid, datauniqueid, filename, Request.Form.Files[0]);
return Ok();
}
protected bool IsIPAddressAllowed()
{
string allowedList = Config[Constants.InboundApiAllowedIPList];
if (string.IsNullOrWhiteSpace(allowedList))
return true;
System.Net.IPAddress remoteIP = HttpContext.Connection.RemoteIpAddress;
byte[] remoteIPBytes = remoteIP.GetAddressBytes();
string[] allowedIPs = allowedList.Split(';');
foreach (string ip in allowedIPs)
{
System.Net.IPAddress parsedIP;
if (System.Net.IPAddress.TryParse(ip, out parsedIP))
{
if (parsedIP.GetAddressBytes().SequenceEqual(remoteIPBytes))
return true;
}
}
return false;
}
}