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