Files
raven/server/AyaNova/Controllers/ExportController.cs
2020-10-23 22:20:55 +00:00

159 lines
6.6 KiB
C#

using System.Collections.Generic;
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 AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using AyaNova.Util;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.IO.Compression;
namespace AyaNova.Api.Controllers
{
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/export")]
[Produces("application/json")]
[Authorize]
public class ExportController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<ExportController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public ExportController(AyContext dbcontext, ILogger<ExportController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Export to file
/// </summary>
/// <param name="format">Valid values are: "csv","json"</param>
/// <param name="dataListSelection"></param>
/// <returns>downloadable export file name</returns>
[HttpPost("render")]
public async Task<IActionResult> RenderExport([FromRoute] string format, [FromBody] DataListSelection dataListSelection)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
if (dataListSelection.IsEmpty)
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "DataListSelection is required"));
if (!dataListSelection.ObjectType.HasAttribute(typeof(CoreBizObjectAttribute)))
return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Not a taggable object type"));
if (!Authorized.HasReadFullRole(HttpContext.Items, dataListSelection.ObjectType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (string.IsNullOrWhiteSpace(format))
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "format required"));
if (format != "csv" && format != "json")
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "format not valid, must be 'csv' or 'json'"));
await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log);
if (dataListSelection.SelectedRowIds.Length == 0)
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids"));
log.LogDebug($"Instantiating biz object handler for {dataListSelection.ObjectType}");
var biz = BizObjectFactory.GetBizObject(dataListSelection.ObjectType, ct);
log.LogDebug($"Fetching data for {dataListSelection.SelectedRowIds.Length} {dataListSelection.ObjectType} items");
var TheData = await ((IExportAbleObject)biz).GetExportData(dataListSelection.SelectedRowIds);
string outputRandomFileNameNoExtension = StringUtil.ReplaceLastOccurrence(FileUtil.NewRandomFileName, ".", "");
string outputSourceFileName = outputRandomFileNameNoExtension + "." + format;
string outputSourceFullPath = System.IO.Path.Combine(FileUtil.TemporaryFilesFolder, outputSourceFileName);
string outputZipFullpath = System.IO.Path.Combine(FileUtil.TemporaryFilesFolder, outputRandomFileNameNoExtension + ".zip");
// string outputFullPathSourceFile=outputFullPathNoExtension
// string outputFullpathZipFile=outputFullPathNoExtension + ".zip";
log.LogDebug($"Calling render export data to file");
switch (format)
{
case "csv":
throw new System.NotImplementedException("CSV export not implemented yet");
break;
case "json":
using (StreamWriter file = System.IO.File.CreateText(outputSourceFullPath))
using (JsonTextWriter writer = new JsonTextWriter(file))
{
TheData.WriteTo(writer);
}
break;
}
//zip it
using (FileStream fs = new FileStream(outputZipFullpath, FileMode.Create))
using (ZipArchive arch = new ZipArchive(fs, ZipArchiveMode.Create))
{
arch.CreateEntryFromFile(outputSourceFullPath, outputSourceFileName);
}
log.LogDebug($"Completed, returning results");
return Ok(ApiOkResponse.Response(outputRandomFileNameNoExtension + ".zip"));
}
/// <summary>
/// Download a rendered Export
/// </summary>
/// <param name="fileName"></param>
/// <param name="t">download token</param>
/// <returns></returns>
[HttpGet("download/{fileName}")]
[AllowAnonymous]
public async Task<IActionResult> DownloadAsync([FromRoute] string fileName, [FromQuery] string t)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (await UserBiz.ValidateDownloadTokenAndReturnUserAsync(t, ct) == null)
{
await Task.Delay(ServerBootConfig.FAILED_AUTH_DELAY);//DOS protection
return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED));
}
if (!FileUtil.TemporaryFileExists(fileName))
{
await Task.Delay(ServerBootConfig.FAILED_AUTH_DELAY);//fishing protection
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
}
var FilePath = FileUtil.GetFullPathForTemporaryFile(fileName);
return PhysicalFile(FilePath, "application/zip");
}
//-----------------------------------------
}//eoc
}//eons