Backup
This commit is contained in:
@@ -9,6 +9,8 @@ using AyaNova.Biz;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AyaNova.Biz;
|
using AyaNova.Biz;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using AyaNova.Util;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//************************************************************************************************************** */
|
//************************************************************************************************************** */
|
||||||
@@ -25,14 +27,8 @@ namespace AyaNova.Api.Controllers
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//FROM DOCS HERE:
|
|
||||||
//https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
|
|
||||||
//https://github.com/aspnet/Docs/tree/74a44669d5e7039e2d4d2cb3f8b0c4ed742d1124/aspnetcore/mvc/models/file-uploads/sample/FileUploadSample
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Backup and restore controller for uploading or downloading backup files
|
/// Backup
|
||||||
/// and triggering a restore from backup
|
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
@@ -78,7 +74,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
return StatusCode(403, new ApiNotAuthorizedResponse());
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||||
|
|
||||||
|
|
||||||
var JobName = $"Backup (on demand)";
|
var JobName = $"Backup (on demand)";
|
||||||
|
|
||||||
OpsJob j = new OpsJob();
|
OpsJob j = new OpsJob();
|
||||||
j.Name = JobName;
|
j.Name = JobName;
|
||||||
@@ -86,148 +82,28 @@ namespace AyaNova.Api.Controllers
|
|||||||
j.JobType = JobType.Backup;
|
j.JobType = JobType.Backup;
|
||||||
j.SubType = JobSubType.NotSet;
|
j.SubType = JobSubType.NotSet;
|
||||||
j.Exclusive = true;
|
j.Exclusive = true;
|
||||||
|
|
||||||
await JobsBiz.AddJobAsync(j, ct);
|
await JobsBiz.AddJobAsync(j, ct);
|
||||||
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerJob, AyaEvent.Created, JobName), ct);
|
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerJob, AyaEvent.Created, JobName), ct);
|
||||||
return Accepted(new { JobId = j.GId });
|
return Accepted(new { JobId = j.GId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get list of backup files
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("list")]
|
||||||
|
public ActionResult ListBackupFiles()
|
||||||
|
{
|
||||||
|
if (serverState.IsClosed)
|
||||||
|
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||||
|
if (!Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull | AuthorizationRoles.OpsAdminLimited))
|
||||||
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||||
|
return Ok(ApiOkResponse.Response(FileUtil.UtilityFileList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region old shit
|
|
||||||
/*
|
|
||||||
LOOKAT:
|
|
||||||
A backup archive consists of a similar format to the v7 data dumper utility, json file per object in subdirectories corresponding to object type all in a zip archive
|
|
||||||
|
|
||||||
Route to trigger restore from selected file
|
|
||||||
Route to force immediate backup
|
|
||||||
Backup code in biz objects "IBackup" interface (which in turn is probably going to implement an IExport interface as it serves dual purpose
|
|
||||||
of exporting data, or maybe that's special purpose custom objects for exporting like csv etc since there is likely a graph of data involved)
|
|
||||||
- object is exported / backed up to json
|
|
||||||
Restore code in biz objects "IRestore" interface
|
|
||||||
- object(s) imported via restore and data given to them or file or whatever (See discource project)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//TODO: Copy the code from ImportAyaNova7Controller upload method instead of this old crap
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// Upload AyaNova backup files
|
|
||||||
// /// **Files of the same name will overwrite without warning**
|
|
||||||
// /// Maximum 10gb
|
|
||||||
// /// </summary>
|
|
||||||
// /// <returns></returns>
|
|
||||||
// [HttpPost("Upload")]
|
|
||||||
// [DisableFormValueModelBinding]
|
|
||||||
// [RequestSizeLimit(10737418241)]//10737418240 = 10gb https://github.com/aspnet/Announcements/issues/267
|
|
||||||
// public async Task<IActionResult> Upload()
|
|
||||||
// {
|
|
||||||
// //Adapted from the example found here: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
|
|
||||||
// {
|
|
||||||
// return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Used to accumulate all the form url encoded key value pairs in the
|
|
||||||
// // request.
|
|
||||||
// var formAccumulator = new KeyValueAccumulator();
|
|
||||||
// //string targetFilePath = null;
|
|
||||||
|
|
||||||
// var boundary = MultipartRequestHelper.GetBoundary(
|
|
||||||
// MediaTypeHeaderValue.Parse(Request.ContentType),
|
|
||||||
// _defaultFormOptions.MultipartBoundaryLengthLimit);
|
|
||||||
// var reader = new MultipartReader(boundary, HttpContext.Request.Body);
|
|
||||||
|
|
||||||
// var section = await reader.ReadNextSectionAsync();
|
|
||||||
|
|
||||||
// while (section != null)
|
|
||||||
// {
|
|
||||||
// ContentDispositionHeaderValue contentDisposition;
|
|
||||||
// var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
|
|
||||||
|
|
||||||
// if (hasContentDispositionHeader)
|
|
||||||
// {
|
|
||||||
// if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
|
|
||||||
// {
|
|
||||||
// //Save file
|
|
||||||
// //as it's just a backup file there is no db involvement at all
|
|
||||||
// FileUtil.storeBackupFile(section.Body, contentDisposition.FileName.Value.Replace("\"",""));
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
|
|
||||||
// {
|
|
||||||
// // Content-Disposition: form-data; name="key"
|
|
||||||
// //
|
|
||||||
// // value
|
|
||||||
|
|
||||||
// // Do not limit the key name length here because the
|
|
||||||
// // multipart headers length limit is already in effect.
|
|
||||||
// var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
|
|
||||||
// var encoding = GetEncoding(section);
|
|
||||||
// using (var streamReader = new StreamReader(
|
|
||||||
// section.Body,
|
|
||||||
// encoding,
|
|
||||||
// detectEncodingFromByteOrderMarks: true,
|
|
||||||
// bufferSize: 1024,
|
|
||||||
// leaveOpen: true))
|
|
||||||
// {
|
|
||||||
// // The value length limit is enforced by MultipartBodyLengthLimit
|
|
||||||
// var value = await streamReader.ReadToEndAsync();
|
|
||||||
// if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
|
|
||||||
// {
|
|
||||||
// value = String.Empty;
|
|
||||||
// }
|
|
||||||
// formAccumulator.Append(key.Value, value);
|
|
||||||
|
|
||||||
// if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
|
|
||||||
// {
|
|
||||||
// throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Drains any remaining section body that has not been consumed and
|
|
||||||
// // reads the headers for the next section.
|
|
||||||
// section = await reader.ReadNextSectionAsync();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// catch (InvalidDataException ex)
|
|
||||||
// {
|
|
||||||
// return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", ex.Message));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return Ok();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// private static Encoding GetEncoding(MultipartSection section)
|
|
||||||
// {
|
|
||||||
// MediaTypeHeaderValue mediaType;
|
|
||||||
// var hasMediaTypeHeader = MediaTypeHeaderValue.TryParse(section.ContentType, out mediaType);
|
|
||||||
// // UTF-7 is insecure and should not be honored. UTF-8 will succeed in
|
|
||||||
// // most cases.
|
|
||||||
// if (!hasMediaTypeHeader || Encoding.UTF7.Equals(mediaType.Encoding))
|
|
||||||
// {
|
|
||||||
// return Encoding.UTF8;
|
|
||||||
// }
|
|
||||||
// return mediaType.Encoding;
|
|
||||||
// }
|
|
||||||
#endregion old shit
|
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
}//eons
|
}//eons
|
||||||
|
|||||||
Reference in New Issue
Block a user