5ced0fec53
- fix warning compilazione - fix auth windows x login
536 lines
18 KiB
C#
536 lines
18 KiB
C#
using Egw.Core;
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using MP.AppAuth.Models;
|
|
using Newtonsoft.Json;
|
|
using RestSharp;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Web;
|
|
|
|
#nullable enable
|
|
|
|
namespace MP.Land.Data
|
|
{
|
|
/// <summary>
|
|
/// Servizi e dati condivisi a livello applicazione
|
|
/// </summary>
|
|
public class LicenseService
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Init classe
|
|
/// </summary>
|
|
/// <param name="configuration"></param>
|
|
/// <param name="logger"></param>
|
|
/// <param name="distributedCache"></param>
|
|
public LicenseService(IConfiguration configuration, ILogger<LicenseService> logger, IDistributedCache distributedCache)
|
|
{
|
|
_logger = logger;
|
|
_configuration = configuration;
|
|
this.distributedCache = distributedCache;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Events
|
|
|
|
public event Action EA_InfoUpdated = null!;
|
|
|
|
#endregion Public Events
|
|
|
|
#region Public Properties
|
|
|
|
public List<LiManObj.AttivazioneDTO> ActivList { get; set; } = new List<LiManObj.AttivazioneDTO>();
|
|
public List<AnagKeyValueModel> AKVList { get; set; } = new List<AnagKeyValueModel>();
|
|
public string Applicazione { get; set; } = "";
|
|
|
|
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);
|
|
|
|
/// <summary>
|
|
/// Codice cliente/installazione
|
|
/// </summary>
|
|
public string Installazione { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Master key licenza principale
|
|
/// </summary>
|
|
public string MasterKey { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Numero licenze da DB
|
|
/// </summary>
|
|
public int NumLicDb { get; set; } = -1;
|
|
|
|
/// <summary>
|
|
/// Numero licenze da auth remota
|
|
/// </summary>
|
|
public int NumLicRemote { get; set; } = -1;
|
|
|
|
public bool ValidData
|
|
{
|
|
get
|
|
{
|
|
// controllo valori string base
|
|
bool checkData = !string.IsNullOrEmpty(Installazione) && !string.IsNullOrEmpty(Applicazione) && !string.IsNullOrEmpty(MasterKey) && ActivList != null && ActivList.Count > 0;
|
|
return checkData;
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
public async Task<List<LiManObj.AttivazioneDTO>> ActivListCache()
|
|
{
|
|
List<LiManObj.AttivazioneDTO> dbResult = new List<LiManObj.AttivazioneDTO>();
|
|
string cacheKey = $"{rKeyAttByLic}:{MasterKey}";
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
var cacheRes = JsonConvert.DeserializeObject<List<LiManObj.AttivazioneDTO>?>(rawData);
|
|
if (cacheRes != null)
|
|
{
|
|
dbResult = cacheRes;
|
|
}
|
|
}
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica attivazione licenza
|
|
/// </summary>
|
|
/// <param name="authKey"></param>
|
|
/// <returns></returns>
|
|
public bool checkLicenseActive(string authKey)
|
|
{
|
|
bool answ = false;
|
|
//cerco anche nelle info AKV
|
|
if (AKVList != null)
|
|
{
|
|
var recLic = AKVList.Where(x => x.ValString == authKey).FirstOrDefault();
|
|
int numLic = 0;
|
|
//cerco in record
|
|
if (recLic != null && recLic.ValInt != null)
|
|
{
|
|
numLic = (int)recLic.ValInt;
|
|
// verifico scadenza licenza!
|
|
DateTime scadenza = licenseManGLS.expiryDateByAuthKey(Installazione, recLic.NomeVar, numLic, authKey);
|
|
answ = scadenza > DateTime.Today;
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"checkLicenseActive | Record non trovato per {authKey}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stato server gestione licenze
|
|
/// </summary>
|
|
public async Task<string> checkLimanServer()
|
|
{
|
|
string answ = "ND";
|
|
// cerco online
|
|
RestClient client = new RestClient(apiUrl);
|
|
var request = new RestRequest($"api/health", Method.Get);
|
|
var response = await client.GetAsync(request);
|
|
// controllo risposta
|
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
|
{
|
|
// verifico risposta
|
|
if (response.Content != null)
|
|
{
|
|
answ = response.Content.Replace("\"", "");
|
|
}
|
|
}
|
|
return await Task.FromResult(answ);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica scadenza licenza
|
|
/// </summary>
|
|
/// <param name="authKey"></param>
|
|
/// <returns></returns>
|
|
public DateTime getLicenseExpiry(string authKey)
|
|
{
|
|
DateTime answ = DateTime.Today.AddDays(-1);
|
|
//cerco anche nelle info AKV
|
|
if (AKVList != null)
|
|
{
|
|
var recLic = AKVList.Where(x => x.ValString == authKey).FirstOrDefault();
|
|
int numLic = 0;
|
|
//cerco in record
|
|
if (recLic != null && recLic.ValInt != null)
|
|
{
|
|
numLic = (int)recLic.ValInt;
|
|
// verifico scadenza licenza!
|
|
DateTime scadenza = licenseManGLS.expiryDateByAuthKey(Installazione, recLic.NomeVar, numLic, authKey);
|
|
answ = scadenza;
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation($"getLicenseExpiry | Record non trovato per {authKey}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init della classe con variabili di base da Redis/DB
|
|
/// </summary>
|
|
public bool InitAkv()
|
|
{
|
|
bool fatto = false;
|
|
Applicazione = "MAPO";
|
|
Installazione = getAVKStr("Installazione");
|
|
MasterKey = getAVKStr(Applicazione);
|
|
NumLicDb = getAVKInt(Applicazione);
|
|
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
|
|
return fatto;
|
|
}
|
|
|
|
public async Task<List<LiManObj.ApplicativoDTO>> LicAppCache()
|
|
{
|
|
List<LiManObj.ApplicativoDTO> dbResult = new List<LiManObj.ApplicativoDTO>();
|
|
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
var cacheRes = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
|
|
if (cacheRes != null)
|
|
{
|
|
dbResult = cacheRes;
|
|
}
|
|
}
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init della classe con variabili di base da Redis/DB
|
|
/// </summary>
|
|
public async Task<bool> RefreshLicense()
|
|
{
|
|
bool fatto = false;
|
|
// scadenza info a 15 gg...
|
|
int numDays = 15;
|
|
|
|
// dati applicativo
|
|
var appData = await OnlineAppInfo();
|
|
if (appData != null)
|
|
{
|
|
if (appData.Count > 0)
|
|
{
|
|
fatto = await setAppInfo(appData, numDays);
|
|
// salvo info licenza...
|
|
NumLicRemote = appData[0].NumLicenze;
|
|
}
|
|
}
|
|
|
|
// dati attivazioni
|
|
var onlineAct = await OnlineActivationList();
|
|
if (onlineAct != null)
|
|
{
|
|
if (onlineAct.Count > 0)
|
|
{
|
|
infoExpiry = DateTime.Now.AddDays(numDays);
|
|
ActivList = onlineAct;
|
|
fatto = await setActivList(onlineAct, numDays);
|
|
}
|
|
}
|
|
await Task.Delay(1);
|
|
return fatto;
|
|
}
|
|
|
|
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> 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 async Task<bool> setAppInfo(List<LiManObj.ApplicativoDTO> newAppInfo, int numDays)
|
|
{
|
|
bool fatto = false;
|
|
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
|
|
var rawData = JsonConvert.SerializeObject(newAppInfo);
|
|
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
|
|
fatto = true;
|
|
if (EA_InfoUpdated != null)
|
|
{
|
|
EA_InfoUpdated?.Invoke();
|
|
}
|
|
return fatto;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// Chiave redis x attivazioni della licenza
|
|
/// </summary>
|
|
protected const string rKeyAttByLic = "LongCache:AttByLic";
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Cerca di recuperare valore INT da elenco AKV
|
|
/// </summary>
|
|
/// <param name="varReq">Chiave AKV richiesta</param>
|
|
/// <returns></returns>
|
|
protected int getAVKInt(string varReq)
|
|
{
|
|
int answ = -9999;
|
|
if (AKVList != null && AKVList.Count > 0)
|
|
{
|
|
var currRec = AKVList.Where(x => x.NomeVar == varReq).FirstOrDefault();
|
|
if (currRec != null)
|
|
{
|
|
answ = currRec.ValInt ?? 0;
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cerca di recuperare valore string da elenco AKV
|
|
/// </summary>
|
|
/// <param name="varReq">Chiave AKV richiesta</param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero chiave da redis
|
|
/// </summary>
|
|
/// <param name="rKey"></param>
|
|
/// <returns></returns>
|
|
protected async Task<string> getRSV(string rKey)
|
|
{
|
|
string answ = "";
|
|
var redisDataList = await distributedCache.GetAsync(rKey);
|
|
if (redisDataList != null)
|
|
{
|
|
answ = Encoding.UTF8.GetString(redisDataList);
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio chiave in redis
|
|
/// </summary>
|
|
/// <param name="rKey"></param>
|
|
/// <param name="rVal"></param>
|
|
/// <param name="cacheMult"></param>
|
|
/// <returns></returns>
|
|
protected async Task<bool> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio chiave in redis
|
|
/// </summary>
|
|
/// <param name="rKey"></param>
|
|
/// <param name="rValInt"></param>
|
|
/// <param name="cacheMult"></param>
|
|
/// <returns></returns>
|
|
protected async Task<bool> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Registra in cache chiave se non fosse già in elenco
|
|
/// </summary>
|
|
/// <param name="newKey"></param>
|
|
protected void trackCache(string newKey)
|
|
{
|
|
if (!cachedDataList.Contains(newKey))
|
|
{
|
|
cachedDataList.Add(newKey);
|
|
}
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private static IConfiguration? _configuration;
|
|
|
|
/// <summary>
|
|
/// URL dell'API x chiamate gestione licenze
|
|
/// </summary>
|
|
private static string apiUrl = "https://liman.egalware.com/ELM.API/";
|
|
|
|
/// <summary>
|
|
/// Chiave redis x info della licenza
|
|
/// </summary>
|
|
private static string rkeyAppInfo = "LongCache:AppInfo";
|
|
|
|
//private static string apiUrl = "https://localhost:44351/";
|
|
private readonly IDistributedCache distributedCache;
|
|
|
|
/// <summary>
|
|
/// Elenco obj in cache
|
|
/// </summary>
|
|
private List<string> cachedDataList = new List<string>();
|
|
|
|
/// <summary>
|
|
/// Fattorte conversione cache sliding --> 1 h
|
|
/// </summary>
|
|
private int cacheFact = 12;
|
|
|
|
/// <summary>
|
|
/// Durata assoluta massima della cache IN SECONDI
|
|
/// </summary>
|
|
private int chAbsExp = 60 * 5;
|
|
|
|
/// <summary>
|
|
/// 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)
|
|
/// </summary>
|
|
private int chSliExp = 60 * 1;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private static ILogger<LicenseService> _logger { get; set; } = null!;
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Opzioni cache con moltiplicatore durata risp durata base (1/5 minuti)
|
|
/// </summary>
|
|
/// <param name="multFact"></param>
|
|
/// <returns></returns>
|
|
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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco attivazioni attuali
|
|
/// </summary>
|
|
private async Task<List<LiManObj.AttivazioneDTO>?> OnlineActivationList()
|
|
{
|
|
List<LiManObj.AttivazioneDTO>? answ = new List<LiManObj.AttivazioneDTO>();
|
|
// 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<List<LiManObj.AttivazioneDTO>?>(rawData);
|
|
}
|
|
return await Task.FromResult(answ);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera info licenza da remoto
|
|
/// </summary>
|
|
private async Task<List<LiManObj.ApplicativoDTO>> OnlineAppInfo()
|
|
{
|
|
List<LiManObj.ApplicativoDTO>? answ = new List<LiManObj.ApplicativoDTO>();
|
|
// cerco online
|
|
RestClient client = new RestClient(apiUrl);
|
|
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
|
|
//string mKey = System.Net.WebUtility.UrlEncode(MasterKey);
|
|
string reqUrl = $"api/licenza/{Installazione}?CodApp={Applicazione}&Chiave={MKeyEnc}";
|
|
var request = new RestRequest(reqUrl, Method.Get);
|
|
var response = await client.GetAsync(request);
|
|
// controllo risposta
|
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
|
{
|
|
// verifico risposta
|
|
string rawData = $"{response.Content}";
|
|
answ = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
|
|
}
|
|
// restituisce valori o insieme vuoto
|
|
return await Task.FromResult(answ ?? new List<LiManObj.ApplicativoDTO>());
|
|
}
|
|
|
|
private void ReportUpdated()
|
|
{
|
|
if (EA_InfoUpdated != null)
|
|
{
|
|
EA_InfoUpdated?.Invoke();
|
|
}
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |