using GPW.CORE.Data; using GPW.CORE.Data.DbModels; using Microsoft.Extensions.Caching.Distributed; using Newtonsoft.Json; using RestSharp; using System.Diagnostics; using System.Text; using System.Web; namespace GPW.CORE.UI.Data { /// /// Servizi e dati condivisi a livello applicazione /// public class LicenseService { #region Private Fields private static ILogger _logger; private static IConfiguration _configuration; private readonly IDistributedCache distributedCache; /// /// Chiave redis x attivazioni della licenza /// protected const string rKeyAttByLic = "LongCache:AttByLic"; /// /// Durata assoluta massima della cache IN SECONDI /// private int chAbsExp = 60 * 5; /// /// Durata della cache IN SECONDI in modalità inattiva (non acceduta) prima di venire rimossa /// NON estende oltre il tempo massimo di validità della cache (chAbsExp) /// private int chSliExp = 60 * 1; /// /// Fattorte conversione cache sliding --> 1 h /// private int cacheFact = 12; /// /// Opzioni cache con moltiplicatore durata risp durata base (1/5 minuti) /// /// /// private DistributedCacheEntryOptions cacheOpt(int multFact) { var numSecAbsExp = chAbsExp * multFact; var numSecSliExp = chSliExp * multFact; return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddSeconds(numSecAbsExp)).SetSlidingExpiration(TimeSpan.FromSeconds(numSecSliExp)); } /// /// Elenco obj in cache /// private List cachedDataList = new List(); /// /// Init classe /// /// /// /// public LicenseService(IConfiguration configuration, ILogger logger, IDistributedCache distributedCache) { _logger = logger; _configuration = configuration; this.distributedCache = distributedCache; } /// /// Recupero chiave da redis /// /// /// protected async Task getRSV(string rKey) { string answ = ""; var redisDataList = await distributedCache.GetAsync(rKey); if (redisDataList != null) { answ = Encoding.UTF8.GetString(redisDataList); } return answ; } /// /// Salvataggio chiave in redis /// /// /// /// /// protected async Task setRSV(string rKey, string rVal, int cacheMult) { bool fatto = false; var redisDataList = Encoding.UTF8.GetBytes(rVal); await distributedCache.SetAsync(rKey, redisDataList, cacheOpt(cacheMult)); fatto = true; return fatto; } /// /// Salvataggio chiave in redis /// /// /// /// /// protected async Task setRSV(string rKey, int rValInt, int cacheMult) { bool fatto = false; var redisDataList = Encoding.UTF8.GetBytes($"{rValInt}"); await distributedCache.SetAsync(rKey, redisDataList, cacheOpt(cacheMult)); fatto = true; return fatto; } /// /// Registra in cache chiave se non fosse già in elenco /// /// protected void trackCache(string newKey) { if (!cachedDataList.Contains(newKey)) { cachedDataList.Add(newKey); } } #endregion Private Fields #region Public Events public event Action EA_InfoUpdated = null!; public List ActivList { get; set; } = new List(); #endregion Public Events #region Public Properties public async Task> ActivListCache() { List dbResult = new List(); string cacheKey = $"{rKeyAttByLic}:{MasterKey}"; trackCache(cacheKey); string rawData = await getRSV(cacheKey); if (!string.IsNullOrEmpty(rawData)) { dbResult = JsonConvert.DeserializeObject>(rawData); } return await Task.FromResult(dbResult); } public async Task setActivList(List newActList, int numDays) { bool fatto = false; string cacheKey = $"{rKeyAttByLic}:{MasterKey}"; var rawData = JsonConvert.SerializeObject(newActList); await setRSV(cacheKey, rawData, numDays * cacheFact * 24); fatto = true; if (EA_InfoUpdated != null) { EA_InfoUpdated?.Invoke(); } return fatto; } public List AKVList { get; set; } = new List(); public string Installazione { get; set; } = ""; public string Applicazione { get; set; } = ""; public string MasterKey { get; set; } = ""; public bool ValidData { get { // controllo valori string base bool checkData = !string.IsNullOrEmpty(Installazione) && !string.IsNullOrEmpty(Applicazione) && !string.IsNullOrEmpty(MasterKey); return checkData; } } public bool HasActivData { get { bool answ = ValidData; // se ok controllo che ci siano attivazioni if (answ) { // provo classe locale... answ = ActivList != null && ActivList.Count > 0; // se non le avessi carico! if (!answ) { var pUpd = Task.Run(async () => { ActivList = await ActivListCache(); }); pUpd.Wait(); } } return answ; } } public DateTime infoExpiry { get; set; } = DateTime.Today.AddDays(1); #endregion Public Properties #region Private Methods private void ReportUpdated() { if (EA_InfoUpdated != null) { EA_InfoUpdated?.Invoke(); } } /// /// Cerca di recuperare valore string da elenco AKV /// /// Chiave AKV richiesta /// protected string getAVKStr(string varReq) { string answ = ""; if (AKVList != null && AKVList.Count > 0) { var currRec = AKVList.Where(x => x.NomeVar == varReq).FirstOrDefault(); if (currRec != null) { answ = $"{currRec.ValString}"; } } return answ; } /// /// Init della classe con variabili di base da Redis/DB /// public bool InitAkv() { bool fatto = false; Installazione = getAVKStr("installazione"); MasterKey = getAVKStr(Installazione); fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}"); return fatto; } /// /// Init della classe con variabili di base da Redis/DB /// public async Task RefreshLicense() { bool fatto = false; var onlineAct = await OnlineActivationList(); if (onlineAct != null) { if (onlineAct.Count > 0) { // scadenza info a 15 gg... int numDays = 15; infoExpiry = DateTime.Now.AddDays(numDays); ActivList = onlineAct; fatto = await setActivList(onlineAct, numDays); } } await Task.Delay(1); return fatto; } /// /// URL dell'API x chiamate gestione licenze /// private static string apiUrl = "https://liman.egalware.com/ELM.API/"; /// /// Elenco attivazioni attuali /// private async Task> OnlineActivationList() { List answ = new List(); // cerco online RestClient client = new RestClient(apiUrl); //client.Authenticator = new HttpBasicAuthenticator("username", "password"); string MKeyEnc = HttpUtility.UrlEncode(MasterKey); var request = new RestRequest($"/api/attivazioni/?chiave={MKeyEnc}", Method.Get); var response = await client.GetAsync(request); // controllo risposta if (response.StatusCode == System.Net.HttpStatusCode.OK) { // salvo in redis contenuto serializzato string rawData = response.Content; answ = JsonConvert.DeserializeObject>(rawData); } return await Task.FromResult(answ); } #endregion Private Methods } }