using Core; using Core.DTO; using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Zip; using LiMan.APi.Data; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using NLog; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace LiMan.APi.Controllers { [Route("api/apptask")] [ApiController] public class AppTaskController : ControllerBase { #region Public Constructors /// /// Init generico /// /// /// /// public AppTaskController(IConfiguration configuration, ApiDataService DataService, IWebHostEnvironment env) { _configuration = configuration; this.env = env; dataService = DataService; Log.Info("Avviata classe TaskController"); } #endregion Public Constructors #region Public Methods /// /// Elimina tutte le registrazioni req/run/done x device /// /// dev richiedente /// Obj AuthDataDTO con chiavi (master o app) [HttpDelete("cleanup/{dev}")] public async Task> TaskClearAll(string dev, [FromBody] TaskResultDTO CurrReq) { Dictionary result = new Dictionary(); // verifica validità richiesta... if (CurrReq.IsValid) { // FixMe ToDo !!! effettuare verifica valori chiavi/imp/device... // elimina tutte le richieste x la macchina... var rawData = dataService.TaskListReset(CurrReq.CodImp); // registro updater... dataService.UpdaterRecordAction(CurrReq.CodImp, "TaskClearAll"); if (rawData != null) { result = rawData; } // salva in redis e toglie dai task da eseguire la richiesta relativa... // registro infine chiamata await dataService.recordCall(dev, CurrReq.CodImp, $"POST:api/apptask/clear/ | {CurrReq.MastKey} | {CurrReq.CodImp}"); } return result; } /// /// Richiede elenco di task da eseguire x il dev richiedente /// /// dev richiedente /// Cod Auth applicativo /// CodImp del dev [HttpGet("pend/{dev}")] public async Task> TaskGetPending(string dev, [FromHeader] string AppKey, [FromHeader] string CodImp) //public async Task>> TaskGetPending(string dev, [FromHeader] string CodInst, [FromHeader] string CodImp) { Dictionary result = new Dictionary(); // verifica validità richiesta... if (!string.IsNullOrEmpty(AppKey) && !string.IsNullOrEmpty(CodImp)) { // FixMe ToDo !!! effettuare verifica valori chiavi/imp/device... // recupero da REDIS le richieste pending x la macchina... result = dataService.TaskListGet(CodImp); // registro updater... dataService.UpdaterRecordAction(CodImp, "TaskGetPending"); // registro infine chiamata await dataService.recordCall(dev, CodImp, $"POST:api/apptask/pending/ | {dev} | {CodImp} | {AppKey}"); } return result; } /// /// Registra risultato esecuzione task richiesti al device /// /// dev richiedente /// Obj AuthDataDTO con chiavi (master o app) [HttpPost("done/{dev}")] public async Task TaskSetDone(string dev, [FromBody] TaskResultDTO CurrReq) { string result = "NA"; // verifica validità richiesta... if (CurrReq.IsValid) { // FixMe ToDo !!! effettuare verifica valori chiavi/imp/device... // recupero da REDIS le richieste pending x la macchina... int numDone = dataService.TaskSetDone(CurrReq.CodImp, CurrReq.DataPayload); // registro updater... dataService.UpdaterRecordAction(CurrReq.CodImp, "TaskSetDone"); result = $"saved {numDone}/{CurrReq.DataPayload.Count}"; // salva in redis e toglie dai task da eseguire la richiesta relativa... // registro infine chiamata await dataService.recordCall(CurrReq.CodImp, CurrReq.CodImp, $"POST:api/apptask/done/ | {CurrReq.MastKey} | {CurrReq.CodImp}"); } return result; } /// /// Registra in esecuzione itask richiesti al device /// /// dev richiedente /// Obj AuthDataDTO con chiavi (master o app) [HttpPost("running/{dev}")] public async Task TaskSetRunning(string dev, [FromBody] TaskResultDTO CurrReq) { string result = "NA"; // verifica validità richiesta... if (CurrReq.IsValid) { // FixMe ToDo !!! effettuare verifica valori chiavi/imp/device... // recupero da REDIS le richieste pending x la macchina... int numDone = dataService.TaskSetRunning(CurrReq.CodImp, CurrReq.DataPayload); // registro updater... dataService.UpdaterRecordAction(CurrReq.CodImp, "TaskSetRunning"); result = $"saved {numDone}/{CurrReq.DataPayload.Count}"; // registro infine chiamata await dataService.recordCall(dev, CurrReq.CodImp, $"POST:api/apptask/running/ | {CurrReq.MastKey} | {CurrReq.CodImp}"); } return result; } /// /// Caricamento file backup applicativo in formato ZIP via FORM POST (backup configurazione applicativo) /// /// Applicazione di riferimento /// Chiave istanza /// CodImpiego istanza /// Richiesta UnZip file post caricamento /// Richiesta di approvazione salvataggio files modificati post upload + unzip /// File da caricare ed estrarre /// [HttpPost("zipbackup")] public async Task> ZipFileSaveExtract([FromForm] string CodApp, [FromForm] string AppKey, [FromForm] string CodImp, [FromForm] bool DoUnzip, [FromForm] bool ForceApprov, [FromForm] IFormFile ZipFile) { // preparo oggetti x risposta var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/api/filesave/"); List uploadResults = new List(); var uploadResult = new UploadResult(); string CodInst = ""; // max 20 mb long maxFileSize = 1024 * 1024 * 20; // in primis verifica CodImp e AppKey var sLicList = await SubLicGet(AppKey, CodImp); if (sLicList == null || sLicList.Count == 0) { Log.Error($"ZipUpload backup failed: received code not validated | CodApp: {CodApp} | AppKey: {AppKey} | CodImp: {CodImp}"); uploadResult.ErrorCode = 3; } else { var fRec = sLicList.FirstOrDefault(); if (fRec == null || fRec.LicenzaNav == null) { Log.Error($"ZipUpload backup failed: Impossible to find CodInst for current data | CodApp: {CodApp} | AppKey: {AppKey} | CodImp: {CodImp}"); uploadResult.ErrorCode = 4; } else { CodInst = fRec.LicenzaNav.CodInst; string fileDir = env.ContentRootPath; string relDir = env.EnvironmentName; string authKey = ""; uploadResult.FileName = ZipFile.FileName; // controllo size e procedo if (ZipFile.Length == 0) { Log.Info($"{ZipFile.FileName} length is 0 (Err: 1)"); uploadResult.ErrorCode = 1; } else if (ZipFile.Length > maxFileSize) { Log.Info($"{ZipFile.FileName} of {CalcSize(ZipFile.Length)} is larger than the limit of {CalcSize(maxFileSize)} (Err: 2)"); uploadResult.ErrorCode = 2; } else { try { relDir = _configuration["ServerConf:FileShareAppBackup"]; fileDir = Path.Combine(relDir, CodApp, CodInst); if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } var filePath = Path.Combine(fileDir, ZipFile.FileName); // elimino se ci fosse già il file... if (System.IO.File.Exists(filePath)) { System.IO.File.Delete(filePath); } // salvo da filestream a file locale using (FileStream fs = new(filePath, FileMode.Create)) { await ZipFile.CopyToAsync(fs); } // log! Log.Info($"{ZipFile.FileName} saved at {filePath}"); uploadResult.Uploaded = true; uploadResult.StoredFileName = ZipFile.FileName; // se richiesto unzip eseguo if (DoUnzip) { bool extractDone = false; // recupero applicativi connessi var listLic = await dataService.AppDtoSearch(CodInst, CodApp, false); var currLic = listLic.Where(x => x.IsActive).FirstOrDefault(); // procedo SOLO SE ho una licenza attiva x questo cliente if (currLic != null) { // esegue unzip await Task.Run(() => { System.IO.Compression.ZipFile.ExtractToDirectory(filePath, fileDir, true); }); extractDone = true; // elimino zip e altro... if (extractDone) { System.IO.File.Delete(filePath); } // se richiesta auto approvazione eseguo... string reqAppFile = Path.Combine(fileDir, "ChangeApprove.req"); if (System.IO.File.Exists(reqAppFile)) { System.IO.File.Delete(reqAppFile); } if (ForceApprov) { // FixMe ToDo !!! // deve chiamare metodo x approvare, in MP-PROG, la directory dei // documenti caricati.. x ora segnaposto con file (così se scansiona // trova e approva)... System.IO.File.WriteAllText(reqAppFile, authKey); } } } } catch (IOException ex) { Log.Error($"{ZipFile.FileName} error on upload (Err: 3): {ex.Message}"); uploadResult.ErrorCode = 3; } } Log.Info($"ZipUpload backup completed | CodInst: {CodInst} | CodApp: {CodApp} | {uploadResults.Count} files"); } } uploadResults.Add(uploadResult); // registro updater... dataService.UpdaterRecordAction(CodImp, "ZipFileSaveExtract"); return new CreatedResult(resourcePath, uploadResult); } #endregion Public Methods #region Protected Properties /// /// Dataservice x accesso DB /// protected ApiDataService dataService { get; set; } = null!; #endregion Protected Properties #region Protected Methods /// /// Restituisce size calcolata /// /// /// protected string CalcSize(long origSize) { return MeasureUtils.SizeSuffix(origSize, 1); } #endregion Protected Methods #region Private Fields private static IConfiguration _configuration; /// /// Classe per logging /// private static Logger Log = LogManager.GetCurrentClassLogger(); private readonly IWebHostEnvironment env; #endregion Private Fields #region Private Methods /// /// Verifica validità codici /// /// /// /// private async Task> SubLicGet(string AppKey, string CodImp) { List listRes = await dataService.AttivazioniGetAppImp(AppKey, CodImp); return listRes; } #endregion Private Methods } }