diff --git a/EgwControlCenter.App/Components/Compo/AuthChallengeMan.razor.cs b/EgwControlCenter.App/Components/Compo/AuthChallengeMan.razor.cs index 1b0c7f5..63ddd89 100644 --- a/EgwControlCenter.App/Components/Compo/AuthChallengeMan.razor.cs +++ b/EgwControlCenter.App/Components/Compo/AuthChallengeMan.razor.cs @@ -152,10 +152,10 @@ namespace EgwControlCenter.App.Components.Compo ACService.DoReloadConfig(); } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { // mi faccio staccare un codice di auth da remoto - passcode = ACService.GetAuthPassocde(); + passcode = await ACService.GetAuthPassocde(); tCounter = startCounter; RunTimer(); // aggancio gestione eventi diff --git a/EgwControlCenter.App/EgwControlCenter.App.csproj b/EgwControlCenter.App/EgwControlCenter.App.csproj index 46d413f..c415dbc 100644 --- a/EgwControlCenter.App/EgwControlCenter.App.csproj +++ b/EgwControlCenter.App/EgwControlCenter.App.csproj @@ -5,7 +5,7 @@ enable true enable - 1.1.2501.0709 + 1.1.2501.0712 Debug;Release;DEBUG_Local diff --git a/EgwControlCenter.App/Properties/PublishProfiles/ClickOnceProfile.pubxml b/EgwControlCenter.App/Properties/PublishProfiles/ClickOnceProfile.pubxml index be18a60..1725a06 100644 --- a/EgwControlCenter.App/Properties/PublishProfiles/ClickOnceProfile.pubxml +++ b/EgwControlCenter.App/Properties/PublishProfiles/ClickOnceProfile.pubxml @@ -4,8 +4,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - 0709 - 1.1.2501.0709 + 0712 + 1.1.2501.0712 True Release True diff --git a/EgwControlCenter.Core/AppControlService.cs b/EgwControlCenter.Core/AppControlService.cs index 4dfd1ce..e4a7885 100644 --- a/EgwControlCenter.Core/AppControlService.cs +++ b/EgwControlCenter.Core/AppControlService.cs @@ -1,4 +1,5 @@ -using EgwControlCenter.Core.DTO; +using DeviceId; +using EgwControlCenter.Core.DTO; using EgwControlCenter.Core.Models; using EgwCoreLib.Utils; using Newtonsoft.Json; @@ -79,14 +80,90 @@ namespace EgwControlCenter.Core private Random rnd = new Random(); /// - /// Restituisce un codice di auth temporaneo da autorizzare + /// Restituisce un codice di auth temporaneo INT da impiegare x autorizzare /// /// - public int GetAuthPassocde() + public async Task GetAuthPassocde() { - // fixme todo !!! implementare da lettura remota oppure gen locale... - int tempCode = rnd.Next(10000000, 99999999); - return tempCode; + int tVal = 0; + //verifico che NON ci sia una richiesta già in corso... + if (CurrEnrollData.IdReq == 0) + { + // in primis preparo dizionario dei dati da allegare alla richiesta + Dictionary reqInfo = new Dictionary(); + // preparo dati DeviceId da allegare in coda + string deviceId = new DeviceIdBuilder() + .AddMachineName() + .AddUserName() + .AddOsVersion() + .OnWindows(windows => windows + .AddMacAddressFromWmi(excludeWireless: true, excludeNonPhysical: true) + .AddProcessorId() + .AddMotherboardSerialNumber() + .AddSystemDriveSerialNumber()) + .ToString(); + // aggiungo dati MachineInfo... + reqInfo = MachineDataValidator.userInfo; + foreach (var item in MachineDataValidator.netInfo) + { + if (!reqInfo.ContainsKey(item.Key)) + { + reqInfo.Add(item.Key, item.Value); + } + } + // raggiungo DevideID + reqInfo.Add("DeviceID", deviceId); + + // faccio la chiamata rest e salvo risposta... + CurrEnrollData = await CurrCheck.GetNewEnroll(reqInfo); + } + + // risposta valida se trovo un id richeista > 0... + if (CurrEnrollData.IdReq > 0) + { + tVal = CurrEnrollData.Passcode; + } + return tVal; + } + + /// + /// Verifica se sia stato assegnato il codice licenza x una richiesta di enroll e nel caso recupera licenza e restituisce il codice da salvare in conf + /// + /// + public async Task CheckAssignIdxLic() + { + string tVal = ""; + // verifico dati richeista enroll, altrimenti faccio refresh richiesta... + if (CurrEnrollData.IdReq == 0) + { + int newCode = await GetAuthPassocde(); + } + // recupero info + EnrollRequestDTO updRec = await CurrCheck.CheckCurrEnroll(); + if (updRec.IdReq > 0) + { + CurrEnrollData = updRec; + // se la licenza è valida --> procedo! + if( updRec.IdxLic>0) + { + LicenzaDTO currLic = await CurrCheck.GetEnrollLic(); + // se licenza valida --> restituisco e salvo! + if(currLic.IsValid && currLic.IsActive) + { + tVal = currLic.Chiave; + } + } + } + return tVal; + } + + /// + /// Richiesta enroll corrente (se presente come file oppure nuova...) + /// + private EnrollRequestDTO CurrEnrollData + { + get => CurrCheck.CurrEnrollData; + set => CurrCheck.CurrEnrollData = value; } /// diff --git a/EgwControlCenter.Core/DTO/EnrollRequestDTO.cs b/EgwControlCenter.Core/DTO/EnrollRequestDTO.cs index af6f53c..166da51 100644 --- a/EgwControlCenter.Core/DTO/EnrollRequestDTO.cs +++ b/EgwControlCenter.Core/DTO/EnrollRequestDTO.cs @@ -14,7 +14,7 @@ namespace EgwControlCenter.Core.DTO /// /// ID univoco richiesta /// - public int IdReq { get; set; } + public int IdReq { get; set; } = 0; /// /// Passcode usato per autorizzare (un valore random NON DUPLICATO con quelli attivi al momento della richiesta) @@ -36,6 +36,11 @@ namespace EgwControlCenter.Core.DTO /// public DateTime? DtAppr { get; set; } = null; + /// + /// Scadenza richiesta + /// + public DateTime DtScadenza { get; set; } = DateTime.Now.AddSeconds(5); + /// /// Username approvatore /// diff --git a/EgwControlCenter.Core/ReleaseChecker.cs b/EgwControlCenter.Core/ReleaseChecker.cs index d4b482d..318b3d4 100644 --- a/EgwControlCenter.Core/ReleaseChecker.cs +++ b/EgwControlCenter.Core/ReleaseChecker.cs @@ -3,16 +3,8 @@ using EgwControlCenter.Core.Models; using Newtonsoft.Json; using NLog; using RestSharp; -using RestSharp.Serializers; -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Web; -using System.Windows.Markup; namespace EgwControlCenter.Core { @@ -61,6 +53,50 @@ namespace EgwControlCenter.Core get => Path.Combine(AppDir, ConfName); } + /// + /// Richiesta enroll corrente (se presente come file oppure nuova...) + /// + public EnrollRequestDTO CurrEnrollData + { + get + { + DateTime adesso = DateTime.Now; + EnrollRequestDTO answ = new EnrollRequestDTO(); + // cerco se presente il file di enroll request + if (File.Exists(EnrollReqPath)) + { + // leggo il file e verifico sia ancora valido... + var rawData = File.ReadAllText(EnrollReqPath); + if (!string.IsNullOrEmpty(rawData)) + { + answ = JsonConvert.DeserializeObject(rawData) ?? new EnrollRequestDTO(); + // verifico validità scadenza... + if (answ.DtScadenza < adesso) + { + answ = new EnrollRequestDTO(); + // elimino file scaduto... + File.Delete(EnrollReqPath); + } + } + } + return answ; + } + set + { + DateTime adesso = DateTime.Now; + // verifico la scadenza sia valida... + if (value.DtScadenza > adesso) + { + // salvo! + var rawData = JsonConvert.SerializeObject(value, Formatting.Indented); + if (rawData != null && rawData.Length > 2) + { + File.WriteAllText(EnrollReqPath, rawData); + } + } + } + } + /// /// Configurazione degli oggetti da monitorare /// @@ -163,6 +199,50 @@ namespace EgwControlCenter.Core return setUpdated; } + /// + /// Verifica se il server remoto sia in buono stato... + /// + /// + public async Task CheckRemote() + { + // in questo caso la richiesta è per la generica app UpdateManager... + string CodApp = "UpdateManager"; + bool answ = false; + try + { + // client chiamate rest + var client = new RestClient(restOptFast); + // provo cmq ad inizializzare la richiesta + ReleaseReqDTO reqDto = new ReleaseReqDTO() + { + CodApp = CodApp, + CodImp = CurrPatrolCont.CodImpiego, + AppKey = CurrPatrolCont.AppKey + }; + // Chiamo il metodo! + if (useAppKey && reqDto.IsValid) + { + var actReq = new RestRequest($"/api/health", Method.Get); + // effettuo vera chiamata + var currResp = await client.GetAsync(actReq); + if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) + { + var rawData = $"{currResp.Content}"; + answ = rawData.Contains("OK", StringComparison.InvariantCultureIgnoreCase); + } + else + { + Log.Error($"Errore in ricezione info REST CheckRemote | StatusCode: {currResp.StatusCode} | content: {currResp.Content}"); + } + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in fase gestione REST services CheckRemote{Environment.NewLine}{exc}"); + } + return answ; + } + /// /// Esegue verifica remota versioni x i sw tracciati /// @@ -197,6 +277,119 @@ namespace EgwControlCenter.Core return fatto; } + /// + /// Effettua un tentativo di enroll richiedendo info x gestione auth + /// + /// Dizionario info da associare all'enroll + /// + public async Task GetNewEnroll(Dictionary InfoData) + { + EnrollRequestDTO answ = new EnrollRequestDTO(); + try + { + // client chiamate rest + var client = new RestClient(restOptStd); + // Chiamo il metodo! + var actReq = new RestRequest($"/api/enroller/getNewEnrollRec", Method.Post); + string payload = JsonConvert.SerializeObject(InfoData); + actReq.AddJsonBody(payload); + // effettuo vera chiamata + var currResp = await client.PostAsync(actReq); + if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) + { + // mi restituisce info + var recEnroll = JsonConvert.DeserializeObject(currResp.Content); + if (recEnroll != null) + { + // verifico che contenga il dizionario allegato alla richiesta... + if (Utils.CompareDict(recEnroll.DictAttrib, InfoData)) + { + answ = recEnroll; + } + } + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in fase gestione REST services GetNewEnroll{Environment.NewLine}{exc}"); + } + + return answ; + } + + /// + /// Effettua verifica stato record enroll (dato valore EnrollData...) + /// + /// + public async Task CheckCurrEnroll() + { + EnrollRequestDTO answ = new EnrollRequestDTO(); + // procedo se ho valori in CurrEnrollData... + if (CurrEnrollData.IdReq > 0) + { + try + { + // client chiamate rest + var client = new RestClient(restOptStd); + // Chiamo il metodo! + var actReq = new RestRequest($"/api/enroller/{CurrEnrollData.IdReq}?passcode={CurrEnrollData.Passcode}", Method.Get); + // effettuo vera chiamata + var currResp = await client.GetAsync(actReq); + if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) + { + // mi restituisce info + var recEnroll = JsonConvert.DeserializeObject(currResp.Content); + if (recEnroll != null) + { + answ = recEnroll; + } + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in fase gestione REST services CheckCurrEnroll{Environment.NewLine}{exc}"); + } + } + + return answ; + } + + /// + /// Effettua verifica stato record enroll + /// + /// + public async Task GetEnrollLic() + { + LicenzaDTO answ = new LicenzaDTO(); + // procedo se ho valori in CurrEnrollData... + if (CurrEnrollData.IdReq > 0) + { + try + { + // client chiamate rest + var client = new RestClient(restOptStd); + // Chiamo il metodo! + var actReq = new RestRequest($"/api/enroller/getLicense/{CurrEnrollData.IdReq}?passcode={CurrEnrollData.Passcode}&idLic={CurrEnrollData.IdxLic}", Method.Get); + // effettuo vera chiamata + var currResp = await client.GetAsync(actReq); + if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) + { + // mi restituisce info + var recEnroll = JsonConvert.DeserializeObject(currResp.Content); + if (recEnroll != null) + { + answ = recEnroll; + } + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in fase gestione REST services GetEnrollLic{Environment.NewLine}{exc}"); + } + } + return answ; + } + public bool HasUpdate() { bool answ = false; @@ -431,13 +624,6 @@ namespace EgwControlCenter.Core /// private static Logger Log = LogManager.GetCurrentClassLogger(); - /// - /// Conf client RestSharp standard: - /// - base URI al sito - /// - timeout 1 min - /// - private static RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60), BaseUrl = new Uri(Const.apiUrl) }; - /// /// Conf client RestSharp fast (usato x check remote): /// - base URI al sito @@ -445,6 +631,13 @@ namespace EgwControlCenter.Core /// private static RestClientOptions restOptFast = new RestClientOptions { Timeout = TimeSpan.FromSeconds(5), BaseUrl = new Uri(Const.apiUrl) }; + /// + /// Conf client RestSharp standard: + /// - base URI al sito + /// - timeout 1 min + /// + private static RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60), BaseUrl = new Uri(Const.apiUrl) }; + private Random rnd = new Random(); /// @@ -462,6 +655,15 @@ namespace EgwControlCenter.Core private Dictionary CriticalRelCurrent { get; set; } = new Dictionary(); private string DataDir { get; set; } = ""; + /// + /// Path file salvataggio Enroll Request (se presente) + /// + private string EnrollReqPath + { + get => Path.Combine(DataDir, ERName); + } + + private string ERName { get; set; } = "EnrollReq.json"; private string LSName { get; set; } = "LastStatus.json"; /// @@ -587,6 +789,35 @@ namespace EgwControlCenter.Core return answ; } + /// + /// Recupera oggetto releaseDTO da file exe indicato analizzando ver number + /// + /// + /// + private ReleaseDTO? ExeGetRelease(string filePath, bool canInstall) + { + ReleaseDTO? answ = null; + if (File.Exists(filePath)) + { + FileVersionInfo fileVersInfo = FileVersionInfo.GetVersionInfo(filePath); + // string codApp = fileVersInfo.ProductName; + string codApp = Path.GetFileNameWithoutExtension(filePath); + string versNum = $"{fileVersInfo.ProductVersion}"; + string versTxt = $"{fileVersInfo.FileVersion}"; + // creo OBJ e lo restituisco... + answ = new ReleaseDTO() + { + CodApp = codApp, + LocalPath = filePath, + ReleaseDate = DateTime.Now, + VersNum = versNum, + VersText = versTxt, + CanInstall = canInstall + }; + } + return answ; + } + /// /// Recupera elenco applicazioni con ultima release CRITICAL /// @@ -697,51 +928,6 @@ namespace EgwControlCenter.Core return answ; } - - /// - /// Verifica se il server remoto sia in buono stato... - /// - /// - public async Task CheckRemote() - { - // in questo caso la richiesta è per la generica app UpdateManager... - string CodApp = "UpdateManager"; - bool answ = false; - try - { - // client chiamate rest - var client = new RestClient(restOptFast); - // provo cmq ad inizializzare la richiesta - ReleaseReqDTO reqDto = new ReleaseReqDTO() - { - CodApp = CodApp, - CodImp = CurrPatrolCont.CodImpiego, - AppKey = CurrPatrolCont.AppKey - }; - // Chiamo il metodo! - if (useAppKey && reqDto.IsValid) - { - var actReq = new RestRequest($"/api/health", Method.Get); - // effettuo vera chiamata - var currResp = await client.GetAsync(actReq); - if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) - { - var rawData = $"{currResp.Content}"; - answ = rawData.Contains("OK", StringComparison.InvariantCultureIgnoreCase); - } - else - { - Log.Error($"Errore in ricezione info REST CheckRemote | StatusCode: {currResp.StatusCode} | content: {currResp.Content}"); - } - } - } - catch (Exception exc) - { - Log.Error($"Eccezione in fase gestione REST services CheckRemote{Environment.NewLine}{exc}"); - } - return answ; - } - /// /// init privato oggetti /// @@ -829,35 +1015,6 @@ namespace EgwControlCenter.Core return answ; } - /// - /// Recupera oggetto releaseDTO da file exe indicato analizzando ver number - /// - /// - /// - private ReleaseDTO? ExeGetRelease(string filePath, bool canInstall) - { - ReleaseDTO? answ = null; - if (File.Exists(filePath)) - { - FileVersionInfo fileVersInfo = FileVersionInfo.GetVersionInfo(filePath); - // string codApp = fileVersInfo.ProductName; - string codApp = Path.GetFileNameWithoutExtension(filePath); - string versNum = $"{fileVersInfo.ProductVersion}"; - string versTxt = $"{fileVersInfo.FileVersion}"; - // creo OBJ e lo restituisco... - answ = new ReleaseDTO() - { - CodApp = codApp, - LocalPath = filePath, - ReleaseDate = DateTime.Now, - VersNum = versNum, - VersText = versTxt, - CanInstall = canInstall - }; - } - return answ; - } - /// /// Rilegge i dati di configurazione e ultimo stato salvato /// diff --git a/EgwControlCenter.Core/Utils.cs b/EgwControlCenter.Core/Utils.cs new file mode 100644 index 0000000..cbb7440 --- /dev/null +++ b/EgwControlCenter.Core/Utils.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwControlCenter.Core +{ + public class Utils + { + /// + /// Comparazione tra 2 dizionari + /// + /// + /// + /// + public static bool CompareDict(Dictionary dict1, Dictionary dict2) + { + bool areEqual = true; + + if (dict1.Count != dict2.Count) + { + areEqual = false; + } + else + { + // ciclo da dict1 ogni valore che so essere in ugual numero in dict2 + foreach (var kvp in dict1) + { + if (!dict2.TryGetValue(kvp.Key, out string? value) || value != kvp.Value) + { + areEqual = false; + break; + } + } + } + return areEqual; + } + } +} diff --git a/README.md b/README.md index 97b1a0d..215feb5 100644 --- a/README.md +++ b/README.md @@ -51,5 +51,6 @@ In caso di chiave esistente ma piena, si deve procedere modificando la chiave di Date | Vers | Note ---------|----------|--------- 2024.09.01 | 1.0.2409.* | Prima versione WinForm only, NET 8 -2024.09.27 | 1.1.2409.* | Versione NET 8 con WinForm + BLAZOR + integrazione LiMan completa e testata x Macchine +2024.10.02 | 1.1.2410.* | Versione NET 8 con WinForm + BLAZOR + integrazione LiMan completa e testata x Macchine 2024.12.24 | 1.1.2412.* | Inizio gestione applicativi IOB-WIN e IOB-MAN, compreso download + install +2025.01.07 | 1.2.2501.* | Gestione auth TOTP applicativi con LiMan inserita diff --git a/README.pdf b/README.pdf index 050495e..9f5cc7e 100644 Binary files a/README.pdf and b/README.pdf differ