169 lines
5.5 KiB
C#
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;
|
|
}
|
|
|
|
} |