using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; using System.Threading.Tasks; using AyaNova.Util; using System; using Microsoft.AspNetCore.Http; namespace AyaNova.Api.Controllers { /// /// Backup /// /// [ApiController] [ApiVersion("8.0")] [Route("api/v{version:apiVersion}/backup")] [Produces("application/json")] public class BackupController : ControllerBase { private readonly AyContext ct; private readonly ILogger log; private readonly ApiServerState serverState; /// /// /// /// /// /// public BackupController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; serverState = apiServerState; } //DANGER: MUST ADD AUTHORIZE ATTRIBUTE TO ANY NEW ROUTES //[Authorize] /// /// Trigger immediate system backup /// /// /// Job Id [HttpPost("backup-now")] [Authorize] public async Task PostBackupNow() { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.Backup))//technically maybe this could be wider open, but for now keeping as locked down return StatusCode(403, new ApiNotAuthorizedResponse()); var JobName = $"LT:BackupNow LT:User {UserNameFromContext.Name(HttpContext.Items)}"; OpsJob j = new OpsJob(); j.Name = JobName; j.AType = AyaType.NoType; j.JobType = JobType.Backup; j.SubType = JobSubType.NotSet; j.Exclusive = true; await JobsBiz.AddJobAsync(j); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerJob, AyaEvent.Created, JobName), ct); return Accepted(new { JobId = j.GId }); } /// /// Get status of backup /// /// [HttpGet("status")] [Authorize] public ActionResult BackupStatus() { //Need size and more info if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Backup)) return StatusCode(403, new ApiNotAuthorizedResponse()); return Ok(ApiOkResponse.Response(FileUtil.BackupStatusReport())); } /// /// Download a backup file /// /// /// download token /// [HttpGet("download/{fileName}")] public async Task DownloadAsync([FromRoute] string fileName, [FromQuery] string t) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); var DownloadUser = await UserBiz.ValidateDownloadTokenAndReturnUserAsync(t, ct); if (DownloadUser == null) { await Task.Delay(AyaNova.Util.ServerBootConfig.FAILED_AUTH_DELAY);//DOS protection return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); } if (!Authorized.HasModifyRole(DownloadUser.Roles, AyaType.Backup))//not technically modify but treating as such as a backup is very sensitive data { await Task.Delay(AyaNova.Util.ServerBootConfig.FAILED_AUTH_DELAY);//DOS protection return StatusCode(403, new ApiNotAuthorizedResponse()); } if (!FileUtil.BackupFileExists(fileName)) { await Task.Delay(AyaNova.Util.ServerBootConfig.FAILED_AUTH_DELAY);//fishing protection return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } string mimetype = fileName.EndsWith("zip") ? "application/zip" : "application/octet-stream"; var utilityFilePath = FileUtil.GetFullPathForBackupFile(fileName); await EventLogProcessor.LogEventToDatabaseAsync(new Event(DownloadUser.Id, 0, AyaType.NoType, AyaEvent.UtilityFileDownload, fileName), ct); return PhysicalFile(utilityFilePath, mimetype, fileName); } /// /// Delete Backup /// /// /// NoContent [HttpDelete("{name}")] [Authorize] public ActionResult DeleteBackupFile([FromRoute] string name) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); CustomerBiz biz = CustomerBiz.GetBiz(ct, HttpContext); if (!Authorized.HasDeleteRole(HttpContext.Items, AyaType.Backup)) return StatusCode(403, new ApiNotAuthorizedResponse()); FileUtil.EraseBackupFile(name); //never errors only no content return NoContent(); } //DANGER: MUST ADD AUTHORIZE ATTRIBUTE TO ANY NEW ROUTES //[Authorize] }//eoc }//eons