281 lines
11 KiB
C#
281 lines
11 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Microsoft.AspNetCore.Http.Features;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.AspNetCore.WebUtilities;
|
|
using Microsoft.Net.Http.Headers;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Newtonsoft.Json.Linq;
|
|
using AyaNova.Models;
|
|
using AyaNova.Api.ControllerHelpers;
|
|
using AyaNova.Util;
|
|
using AyaNova.Biz;
|
|
|
|
|
|
namespace AyaNova.Api.Controllers
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
/// Import AyaNova 7 data controller
|
|
/// </summary>
|
|
[ApiController]
|
|
[ApiVersion("8.0")]
|
|
[Route("api/v{version:apiVersion}/[controller]")]
|
|
[Produces("application/json")]
|
|
[Authorize]
|
|
public class ImportAyaNova7Controller : ControllerBase
|
|
{
|
|
private readonly AyContext ct;
|
|
private readonly ILogger<ImportAyaNova7Controller> log;
|
|
private readonly ApiServerState serverState;
|
|
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="dbcontext"></param>
|
|
/// <param name="logger"></param>
|
|
/// <param name="apiServerState"></param>
|
|
public ImportAyaNova7Controller(AyContext dbcontext, ILogger<ImportAyaNova7Controller> logger, ApiServerState apiServerState)
|
|
{
|
|
ct = dbcontext;
|
|
log = logger;
|
|
serverState = apiServerState;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Upload AyaNova 7 import file
|
|
/// Required roles: OpsAdminFull
|
|
/// </summary>
|
|
/// <returns>NameValue list of filenames and id's</returns>
|
|
[HttpPost]
|
|
[DisableFormValueModelBinding]
|
|
[RequestSizeLimit(10737418241)]//10737418240 = 10gb https://github.com/aspnet/Announcements/issues/267
|
|
public async Task<IActionResult> Upload()
|
|
{
|
|
//Open or opsOnly and user is opsadminfull
|
|
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
|
|
{
|
|
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
|
}
|
|
|
|
if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.AyaNova7Import))
|
|
{
|
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
|
}
|
|
|
|
|
|
var returnList = new List<String>();
|
|
|
|
try
|
|
{
|
|
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
|
|
{
|
|
return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}"));
|
|
}
|
|
|
|
var uploadFormData = await ApiUploadProcessor.ProcessUtilityFileUpload(HttpContext);
|
|
|
|
bool badRequest = false;
|
|
|
|
string errorMessage = string.Empty;
|
|
|
|
//are these the right files?
|
|
if (uploadFormData.UploadedFiles.Count > 0)
|
|
{
|
|
foreach (UploadedFileInfo a in uploadFormData.UploadedFiles)
|
|
{
|
|
//should look like this: ayanova.data.dump.2018-04-2--12-30-57.zip
|
|
string lwr = a.OriginalFileName.ToLowerInvariant();
|
|
if (!(lwr.StartsWith("ayanova.data.dump") && lwr.EndsWith(".zip")))
|
|
{
|
|
badRequest = true;
|
|
errorMessage = $"File uploaded \"{lwr}\" does not appear to be an AyaNova 7 data dump file. The name should start with \"ayanova.data.dump\" have a date in the middle and end with \".zip\". Upload process is terminated without saving.";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (badRequest)
|
|
{
|
|
//delete temp files
|
|
if (uploadFormData.UploadedFiles.Count > 0)
|
|
{
|
|
foreach (UploadedFileInfo a in uploadFormData.UploadedFiles)
|
|
{
|
|
System.IO.File.Delete(a.InitialUploadedPathName);
|
|
}
|
|
}
|
|
//return bad request
|
|
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, errorMessage));
|
|
}
|
|
|
|
|
|
//We have our files and a confirmed AyObject, ready to attach and save permanently
|
|
if (uploadFormData.UploadedFiles.Count > 0)
|
|
{
|
|
foreach (UploadedFileInfo a in uploadFormData.UploadedFiles)
|
|
{
|
|
returnList.Add(a.OriginalFileName);
|
|
}
|
|
}
|
|
}
|
|
catch (InvalidDataException ex)
|
|
{
|
|
return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", ex.Message));
|
|
}
|
|
|
|
//Return the list of attachment ids and filenames
|
|
return Ok(ApiOkResponse.Response(returnList, true));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Delete import file
|
|
///
|
|
/// Required roles: OpsAdminFull
|
|
/// </summary>
|
|
/// <param name="filename"></param>
|
|
/// <returns>Ok</returns>
|
|
[HttpDelete("{filename}")]
|
|
public ActionResult Delete([FromRoute] string filename)
|
|
{
|
|
//Open or opsOnly and user is opsadminfull
|
|
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
|
|
{
|
|
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
|
}
|
|
|
|
if (!ModelState.IsValid)
|
|
{
|
|
return BadRequest(new ApiErrorResponse(ModelState));
|
|
}
|
|
|
|
|
|
if (!Authorized.HasDeleteRole(HttpContext.Items, AyaType.AyaNova7Import))
|
|
{
|
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
|
}
|
|
|
|
//do the delete
|
|
//this handles removing the file if there are no efs left and also the db record for the attachment
|
|
FileUtil.DeleteUtilityFile(filename);
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get AyaNova 7 data dump uploaded files list
|
|
///
|
|
/// Required roles: OpsAdminFull
|
|
/// </summary>
|
|
/// <returns>List of uploaded data dump files</returns>
|
|
[HttpGet]
|
|
public ActionResult List()
|
|
{
|
|
//Open or opsOnly and user is opsadminfull
|
|
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
|
|
{
|
|
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
|
}
|
|
|
|
if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.AyaNova7Import))
|
|
{
|
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
|
}
|
|
|
|
if (!ModelState.IsValid)
|
|
{
|
|
return BadRequest(new ApiErrorResponse(ModelState));
|
|
}
|
|
|
|
//dump file name example: ayanova.data.dump.XXX.zip
|
|
List<string> l = FileUtil.UtilityFileList("ayanova.data.dump.*.zip");
|
|
return Ok(ApiOkResponse.Response(l, true));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// *ERASE DATABASE and start import of previously uploaded import file
|
|
/// **This will permanently erase all current data in database without further warning as the first step in the import process**
|
|
///
|
|
/// Required roles: OpsAdminFull
|
|
///
|
|
/// </summary>
|
|
/// <param name="filename"></param>
|
|
/// <returns>Ok</returns>
|
|
[HttpPost("startImport/{filename}")]
|
|
public ActionResult StartImport([FromRoute] string filename)
|
|
{
|
|
//Open or opsOnly and user is opsadminfull
|
|
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
|
|
{
|
|
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
|
}
|
|
|
|
if (!ModelState.IsValid)
|
|
{
|
|
return BadRequest(new ApiErrorResponse(ModelState));
|
|
}
|
|
|
|
//UPDATE: I think it should be ok so commenting this out for now pending something coming up in testing
|
|
// //LOOKAT: I decided not to allow trial to import v7 data.
|
|
// //This was a snap decision, I didn't think about it much other than
|
|
// //I'm concerned right now as of April 17 2018 during development that
|
|
// //a trial user will import their old AyaNova data and then ... well somehow continue to use it I guess,
|
|
// //maybe it's a non-issue as a trial will only work so long anyway
|
|
// #if (!DEBUG)
|
|
// if (AyaNova.Core.License.LicenseIsTrial)
|
|
// {
|
|
// return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Current license is a trial license key. Only a licensed database can be used with import."));
|
|
// }
|
|
// #endif
|
|
|
|
//Create, in that they are creating new data in AyaNova
|
|
if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.AyaNova7Import))
|
|
{
|
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
|
}
|
|
|
|
//does the file even exist?
|
|
if (!FileUtil.UtilityFileExists(filename))
|
|
{
|
|
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND, "filename", "File not found, ensure the name via the GET route endpoint list of previously uploaded import files"));
|
|
}
|
|
|
|
|
|
//Create the job here
|
|
dynamic jobInfo = new JObject();
|
|
jobInfo.ImportFileName = filename;
|
|
|
|
OpsJob j = new OpsJob();
|
|
j.Name = $"Import AyaNova7 data (import file \"{filename}\"";
|
|
j.JobType = JobType.ImportV7Data;
|
|
//j.O wnerId = UserIdFromContext.Id(HttpContext.Items);
|
|
j.JobInfo = jobInfo.ToString();
|
|
JobsBiz.AddJob(j, ct);
|
|
return Accepted(new { JobId = j.GId });//202 accepted
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
}//eoc
|
|
}//eons
|
|
|