From 62a044e92e8880846ae791a5ae323ec4e712f323 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 25 Jun 2020 16:00:39 +0000 Subject: [PATCH] --- .../Controllers/TranslationController.cs | 61 ++++++++++++++++--- server/AyaNova/util/FileUtil.cs | 13 ++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/server/AyaNova/Controllers/TranslationController.cs b/server/AyaNova/Controllers/TranslationController.cs index 9bca0d5e..f7ed7ff7 100644 --- a/server/AyaNova/Controllers/TranslationController.cs +++ b/server/AyaNova/Controllers/TranslationController.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -12,6 +11,11 @@ using Microsoft.Extensions.Logging; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System.Linq; + namespace AyaNova.Api.Controllers @@ -253,9 +257,11 @@ namespace AyaNova.Api.Controllers /// Get Translation all values /// /// + /// download token /// A single Translation and it's values + [AllowAnonymous] [HttpGet("download/{id}")] - public async Task DownloadTranslation([FromRoute] long id) + public async Task DownloadTranslation([FromRoute] long id, [FromQuery] string t) { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); @@ -266,26 +272,67 @@ namespace AyaNova.Api.Controllers return BadRequest(new ApiErrorResponse(ModelState)); } - //Instantiate the business object handler - TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); - var o = await biz.GetAsync(id); + int nFailedAuthDelay = 3000; + + if (string.IsNullOrWhiteSpace(t)) + { + await Task.Delay(nFailedAuthDelay);//DOS protection + return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); + } + var DownloadUser = await ct.User.AsNoTracking().SingleOrDefaultAsync(z => z.DlKey == t && z.Active == true); + if (DownloadUser == null) + { + await Task.Delay(nFailedAuthDelay);//DOS protection + return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); + } + var utcNow = new DateTimeOffset(DateTime.Now.ToUniversalTime(), TimeSpan.Zero); + if (DownloadUser.DlKeyExpire < utcNow.DateTime) + { + await Task.Delay(nFailedAuthDelay);//DOS protection + return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); + } + + + var o = await ct.Translation.Include(z => z.TranslationItems).SingleOrDefaultAsync(z => z.Id == id); //turn into correct format and then send as file if (o == null) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } - var asText = Newtonsoft.Json.JsonConvert.SerializeObject(o, Newtonsoft.Json.Formatting.None); + var asText = Newtonsoft.Json.JsonConvert.SerializeObject( + o, + Newtonsoft.Json.Formatting.None, + new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(new string[] { "Concurrency", "Id","TranslationId" }) }); var bytes = System.Text.Encoding.UTF8.GetBytes(asText); var file = new FileContentResult(bytes, "application/octet-stream"); - file.FileDownloadName = o.Name + ".json"; + file.FileDownloadName = Util.FileUtil.StringToSafeFileName(o.Name) + ".json"; return file; } + public class ShouldSerializeContractResolver : DefaultContractResolver + { + private readonly IEnumerable _excludePropertyNames; + public ShouldSerializeContractResolver(IEnumerable excludePropertyNames) + { + _excludePropertyNames = excludePropertyNames; + } + + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + IList properties = base.CreateProperties(type, memberSerialization); + + // only serializer properties that start with the specified character + properties = + properties.Where(p => !_excludePropertyNames.Any(p2 => p2 == p.PropertyName)).ToList(); + + return properties; + } + } diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs index e8834636..5a135021 100644 --- a/server/AyaNova/util/FileUtil.cs +++ b/server/AyaNova/util/FileUtil.cs @@ -644,6 +644,19 @@ namespace AyaNova.Util return DateTime.Now.ToString("yyyyMMddHHmmssfff"); } + public static string StringToSafeFileName(string fileName) + {//https://stackoverflow.com/a/3678296/8939 + if (string.IsNullOrWhiteSpace(fileName)) + return "no_name"; + + char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); + // Builds a string out of valid chars and an _ for invalid ones + var ret = new string(fileName.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray()); + if (string.IsNullOrWhiteSpace(ret)) + return "no_name"; + + return ret; + } #endregion general utilities }//eoc