Files
raven/server/AyaNova/Controllers/LogoController.cs
2020-08-07 22:24:49 +00:00

180 lines
7.2 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.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using System.Linq;
using AyaNova.Util;
using System.IO;
namespace AyaNova.Api.Controllers
{
/// <summary>
/// Logo controller
/// </summary>
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/logo")]
[Produces("application/json")]
[Authorize]
public class LogoController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<LogoController> log;
private readonly ApiServerState serverState;
private const int MAXIMUM_LOGO_SIZE = 512000;//We really don't want it too big or it will slow the fuck down for everything
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public LogoController(AyContext dbcontext, ILogger<LogoController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Get Logo
/// </summary>
/// <param name="size">One of "small", "medium", "large"</param>
/// <returns>A single Logo and it's values</returns>
[AllowAnonymous]
[HttpGet("{size}")]
public async Task<IActionResult> DownloadLogo([FromRoute] string size)
{
if (serverState.IsClosed)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
if (string.IsNullOrWhiteSpace(size))
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, "size", "Size is required and must be one of 'small', 'medium' or 'large'"));
size = size.ToLowerInvariant();
if (size != "small" && size != "medium" && size != "large")
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, "size", "Size parameter must be one of 'small', 'medium' or 'large'"));
var logo = await ct.Logo.SingleOrDefaultAsync();
if (logo == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
switch (size)
{
case "small":
return new FileStreamResult(new MemoryStream(logo.Small), Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse(logo.SmallType));
case "medium":
return new FileStreamResult(new MemoryStream(logo.Medium), Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse(logo.MediumType));
case "large":
return new FileStreamResult(new MemoryStream(logo.Large), Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse(logo.LargeType));
}
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
// var asText = Newtonsoft.Json.JsonConvert.SerializeObject(
// o,
// Newtonsoft.Json.Formatting.None,
// new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "LogoId" }) });
// var bytes = System.Text.Encoding.UTF8.GetBytes(asText);
// var file = new FileContentResult(bytes, "application/octet-stream");
// file.FileDownloadName = Util.FileUtil.StringToSafeFileName(o.Name) + ".json";
// return file;
}
/// <summary>
/// Upload Logo
/// Max 500 KiB total (512000 bytes)
/// Must have full rights to Global object
/// </summary>
/// <param name="size">One of "small", "medium", "large"</param>
/// <returns>Accepted</returns>
[Authorize]
[HttpPost("{size}")]
//[DisableFormValueModelBinding]
[RequestSizeLimit(MAXIMUM_LOGO_SIZE)]//currently export file is 200kb * 50 maximum at a time = 15mb https://github.com/aspnet/Announcements/issues/267
public async Task<IActionResult> UploadAsync([FromRoute] string size)//, List<IFormFile> files /// <param name="files">Logo image file</param>
{
//https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1#upload-small-files-with-buffered-model-binding-to-a-database
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Global))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (string.IsNullOrWhiteSpace(size))
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, "size", "Size is required and must be one of 'small', 'medium' or 'large'"));
size = size.ToLowerInvariant();
if (size != "small" && size != "medium" && size != "large")
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, "size", "Size parameter must be one of 'small', 'medium' or 'large'"));
//get the one and only logo object
var logo = await ct.Logo.FirstOrDefaultAsync();
if (logo == null)
{
logo = new Logo();
ct.Logo.Add(logo);
await ct.SaveChangesAsync();
}
var file = Request.Form.Files[0];
//var file=files[0];
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
if (memoryStream.Length > MAXIMUM_LOGO_SIZE)
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, null, $"Logo files must be smaller than {MAXIMUM_LOGO_SIZE} maximum"));
switch (size)
{
case "small":
logo.Small = memoryStream.ToArray();
logo.SmallType = file.ContentType;
break;
case "medium":
logo.Medium = memoryStream.ToArray();
logo.MediumType = file.ContentType;
break;
case "large":
logo.Large = memoryStream.ToArray();
logo.LargeType = file.ContentType;
break;
}
await ct.SaveChangesAsync();
}
return Accepted();
}
}
}