Merge branch 'release/UpdateLandDownload'

This commit is contained in:
Samuele Locatelli
2022-02-01 14:29:56 +01:00
32 changed files with 1032 additions and 32 deletions
-2
View File
@@ -296,8 +296,6 @@ STAT:release:
paths:
- publish/
script:
- dotnet publish -c Release -o ./publish MP.Land/MP.Land.csproj
- dotnet publish -c Release -o ./publish MP.Prog/MP.Prog.csproj
- dotnet publish -c Release -o ./publish MP.Stats/MP.Stats.csproj
+9
View File
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
+220
View File
@@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Egw.Core
{
public class LiManObj
{
#region Public Enums
public enum StatoRichiesta
{
ND = 0,
Richiesta,
Valutazione,
Approvata,
Rifiutata
}
public enum TipoLicenza
{
ND = 0,
/// <summary>
/// Licenza LEgacy Steamware
/// </summary>
GLS,
/// <summary>
/// Master Key License, che ha una data di scadenza globale ed un token = numero di utenti/token massimi associati
/// </summary>
MasterKey,
/// <summary>
/// UserKey License (licenza che consuma un token utente della licenza master) - es GPW
/// </summary>
UserKey,
/// <summary>
/// Chiave tiupo Checksum basata su licenza masster + checksum MD5 di una serie di dati (child licenses)
/// </summary>
CheckSumKey
}
#endregion Public Enums
#region Public Classes
public class ApplicativoDTO
{
#region Public Properties
public string Chiave { get; set; } = "";
public string CodApp { get; set; } = "";
public string CodInst { get; set; } = "";
public DateTime DataEnigma { get; set; } = DateTime.Today.AddYears(-1);
public string Descrizione { get; set; } = "";
public string Enigma { get; set; } = "";
public int IdxLic { get; set; } = 0;
public bool IsActive
{
get => (Scadenza.Subtract(DateTime.Today).TotalDays > 0);
}
public bool Locked { get; set; } = false;
public int NumLicenze { get; set; } = 0;
public int NumLicenzeAttive { get; set; } = 0;
public string Payload { get; set; } = "";
public DateTime Scadenza { get; set; } = DateTime.Today.AddYears(-1);
public TipoLicenza Tipo { get; set; } = TipoLicenza.ND;
#endregion Public Properties
}
public class AttivazioneDTO
{
#region Public Properties
public string Chiave { get; set; } = "";
public string CodApp { get; set; } = "";
public string CodImpiego { get; set; } = "";
public string CodInst { get; set; } = "";
public string Descrizione { get; set; } = "";
public int IdxLic { get; set; } = 0;
public int IdxSubLic { get; set; } = 0;
public TipoLicenza Tipo { get; set; } = TipoLicenza.UserKey;
public DateTime VetoUnlock { get; set; } = DateTime.Today.AddMonths(2);
#endregion Public Properties
}
public class LicenseCoord
{
#region Public Properties
public string CodApp { get; set; } = "";
public string CodInst { get; set; } = "";
public string Enigma { get; set; } = "";
public string MasterKey { get; set; } = "";
#endregion Public Properties
}
public class SupportRequest
{
#region Public Properties
public string CodApp { get; set; } = "";
public string CodImp { get; set; } = "";
public string CodInst { get; set; } = "";
public string ContactEmail { get; set; } = "";
public string ContactName { get; set; } = "";
public string ContactPhone { get; set; } = "";
public int idxSubLic { get; set; } = 0;
public bool IsValid
{
get => !string.IsNullOrEmpty(MasterKey) && !string.IsNullOrEmpty(ContactName) && !string.IsNullOrEmpty(ContactEmail) && !string.IsNullOrEmpty(CodInst) && !string.IsNullOrEmpty(CodApp);
}
public string MasterKey { get; set; } = "";
public string ReqBody { get; set; } = "";
#endregion Public Properties
}
/// <summary>
/// Oggetto Ticket
/// </summary>
public class TicketDTO
{
#region Public Properties
/// <summary>
/// Codice univoco della sub licenza (opzionale)
/// </summary>
public string CodImpiego { get; set; } = "";
/// <summary>
/// Contatto email del cliente richiedente
/// </summary>
public string ContactEmail { get; set; } = "";
/// <summary>
/// Contatto del cliente richiedente
/// </summary>
public string ContactName { get; set; } = "";
/// <summary>
/// Contatto telefonico del cliente richiedente
/// </summary>
public string ContactPhone { get; set; } = "";
public DateTime DtReq { get; set; } = DateTime.Now;
/// <summary>
/// IDX licenza master
/// </summary>
public int IdxLic { get; set; } = 0;
/// <summary>
/// IDX licenza child (opzionale)
/// </summary>
public int IdxSubLic { get; set; } = 0;
public int IdxTicket { get; set; } = 0;
/// <summary>
/// Motivazione della richiesta
/// </summary>
public string ReqBody { get; set; } = "";
/// <summary>
/// Stato richiesta
/// </summary>
public StatoRichiesta Status { get; set; } = StatoRichiesta.ND;
/// <summary>
/// Risposta alla richiesta
/// </summary>
public string SupplAnsw { get; set; } = "";
/// <summary>
/// Email del responsabile dell'azione (interno - supplier)
/// </summary>
public string SupplEmail { get; set; } = "";
/// <summary>
/// Cod dell'user responsabile dell'azione (interno - supplier)
/// </summary>
public string SupplUserCode { get; set; } = "";
/// <summary>
/// Tipologia di licenza gestita
/// </summary>
public TipoLicenza Tipo { get; set; } = TipoLicenza.UserKey;
#endregion Public Properties
}
public class UserLicenseRequest
{
#region Public Properties
public string MasterKey { get; set; } = "";
public Dictionary<string, string> ParamDict { get; set; } = new Dictionary<string, string>();
#endregion Public Properties
}
#endregion Public Classes
}
}
+186
View File
@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Egw.Core
{
/// <summary>
/// utils x cifrature e Crypto
/// </summary>
public class SteamCrypto
{
#region Public Methods
/// <summary>
/// decifra un messaggio con una password
/// </summary>
/// <param name="Message"></param>
/// <param name="Passphrase"></param>
/// <returns></returns>
public static string DecryptString(string Message, string Passphrase)
{
string answ = Message;
byte[] Results = null;
UTF8Encoding UTF8 = new UTF8Encoding();
// Step 1. We hash the passphrase using MD5
// We use the MD5 hash generator as the result is a 128 bit byte array
// which is a valid length for the TripleDES encoder we use below
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
// Step 2. Create a new TripleDESCryptoServiceProvider object
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
// Step 3. Setup the decoder
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
// Step 4. Convert the input string to a byte[]
byte[] DataToDecrypt = null;
try
{
DataToDecrypt = Convert.FromBase64String(Message);
}
catch
{ }
if (DataToDecrypt != null)
{
// Step 5. Attempt to decrypt the string
try
{
ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
}
finally
{
// Clear the TripleDes and Hashprovider services of any sensitive information
TDESAlgorithm.Clear();
HashProvider.Clear();
}
// Step 6. Return the decrypted string in UTF8 format
answ = UTF8.GetString(Results);
}
return answ;
}
/// <summary>
/// cifra un messaggio con una password
/// </summary>
/// <param name="Message"></param>
/// <param name="Passphrase"></param>
/// <returns></returns>
public static string EncryptString(string Message, string Passphrase)
{
byte[] Results;
UTF8Encoding UTF8 = new UTF8Encoding();
// Step 1. We hash the passphrase using MD5
// We use the MD5 hash generator as the result is a 128 bit byte array
// which is a valid length for the TripleDES encoder we use below
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
// Step 2. Create a new TripleDESCryptoServiceProvider object
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
// Step 3. Setup the encoder
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
// Step 4. Convert the input string to a byte[]
byte[] DataToEncrypt = UTF8.GetBytes(Message);
// Step 5. Attempt to encrypt the string
try
{
ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
}
finally
{
// Clear the TripleDes and Hashprovider services of any sensitive information
TDESAlgorithm.Clear();
HashProvider.Clear();
}
// Step 6. Return the encrypted string as a base64 encoded string
return Convert.ToBase64String(Results);
}
/// <summary>
/// genera hash di una stringa in MD5 (es x hash gravatar)
/// </summary>
/// <param name="Message"></param>
/// <returns></returns>
public static string getHashStringMD5(string Message)
{
string hash = "";
using (MD5 md5Hash = MD5.Create())
{
hash = GetMd5Hash(md5Hash, Message);
}
return hash;
}
/// <summary>
/// Crea un hash MD5
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <returns></returns>
public static string GetMd5Hash(MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
/// <summary>
/// Verify a hash against a string.
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <param name="hash"></param>
/// <returns></returns>
public static bool VerifyMd5Hash(MD5 md5Hash, string input, string hash)
{
// Hash the input.
string hashOfInput = GetMd5Hash(md5Hash, input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
{
return true;
}
else
{
return false;
}
}
#endregion Public Methods
}
}
+98
View File
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Egw.Core
{
/// <summary>
/// Gestione licenze applicativi GLS (Legacy SteamWare)
/// </summary>
public class licenseManGLS
{
#region Public Methods
/// <summary>
/// restituisce data decodificata da authKey + applicazione + cliente...
/// </summary>
/// <param name="cliente">The cliente.</param>
/// <param name="applicativo">The applicativo.</param>
/// <param name="licenze">The licenze.</param>
/// <param name="authKey">The authentication key.</param>
/// <returns></returns>
public static DateTime expiryDateByAuthKey(string cliente, string applicativo, int licenze, string authKey)
{
DateTime answ = DateTime.Today.AddYears(-10);
string plainAuthKey = "";
try
{
string passPhrase = string.Format("{0}|{1}", cliente.PadLeft(50, ':'), applicativo);
plainAuthKey = SteamCrypto.DecryptString(authKey, passPhrase); // uso combinazione cliente+applicativo come passphrase!
answ = Convert.ToDateTime(plainAuthKey.Replace(string.Format("{0}#{1}-", cliente, applicativo.PadLeft(20, '-')), "").Replace(string.Format("%{0}%", licenze), ""));
}
catch (Exception exc)
{
//logger.lg.scriviLog(string.Format("Errore decodifica auth key:{0}AuthKey: {1}{0}cliente:{2}{0}applicativo:{3}{0}errore:{4}", Environment.NewLine, authKey, cliente, applicativo, exc), tipoLog.EXCEPTION);
}
return answ;
}
/// <summary>
/// Fornisce chiave MD5 x un cliente/applicativo/expiryDate
/// </summary>
/// <param name="cliente"></param>
/// <param name="applicativo"></param>
/// <param name="licenze"></param>
/// <param name="expiryDate"></param>
/// <returns></returns>
public static string getAuthKey(string cliente, string applicativo, int licenze, DateTime expiryDate)
{
string answ = "";
// algoritmo MD5 formato cliente#applicativo#expDate, via SQLdiventa
// SELECT CONVERT(VARCHAR(32), HashBytes('MD5', 'ETS#GPW#2013/12/31'), 2)
string plainAuthKey = string.Format("{0}#{1}-{2}%{3}%", cliente, applicativo.PadLeft(20, '-'), expiryDate.ToString("yyyy/MM/dd"), licenze);
string passPhrase = string.Format("{0}|{1}", cliente.PadLeft(50, ':'), applicativo);
answ = SteamCrypto.EncryptString(plainAuthKey, passPhrase); // uso combinazione cliente+applicativo come passphrase!
return answ;
}
/// <summary>
/// Fornisce chiave MD5 x una chiave secondaria/di checksum data dai parametri in ingresso
/// MasterKey/string[] chiavi singole child/expiryDate
/// </summary>
/// <param name="MasterKey">Chiave master da cui si parte</param>
/// <param name="Payload">Payload che contiene le chiavi SUB (child) riferite alla master in formato JSon (compresso/no indent)</param>
/// <returns></returns>
public static string getChecksumKey(string MasterKey, string Payload)
{
string answ = "";
answ = SteamCrypto.EncryptString(Payload, MasterKey);
return answ;
}
/// <summary>
/// numero di licenze attive per cliente/applicativo
/// </summary>
/// <param name="cliente"></param>
/// <param name="applicativo"></param>
/// <returns></returns>
public static int getLicenseNum(string cliente, string applicativo)
{
// !!!FARE!!! chiamata a webservice 1/mese
int answ = 1;
// molto hard-coded e discutibile... licenze "perenni"
switch (cliente)
{
default:
answ = 1;
break;
}
return answ;
}
#endregion Public Methods
}
}
+8 -2
View File
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31229.75
# Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Land", "MP.Land\MP.Land.csproj", "{D949AB45-9B65-4594-A97E-182BC3831707}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.AppAuth", "MP.AppAuth\MP.AppAuth.csproj", "{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Egw.Core", "Egw.Core\Egw.Core.csproj", "{D3D348EF-1313-43DF-94FB-28CD38B68212}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Release|Any CPU.Build.0 = Release|Any CPU
{D3D348EF-1313-43DF-94FB-28CD38B68212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3D348EF-1313-43DF-94FB-28CD38B68212}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3D348EF-1313-43DF-94FB-28CD38B68212}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3D348EF-1313-43DF-94FB-28CD38B68212}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+2 -2
View File
@@ -42,9 +42,9 @@ namespace MP.AppAuth.Controllers
/// Elenco Record x AnagKeyValue
/// </summary>
/// <returns></returns>
public List<Models.AnagKeyValue> AnagKeyValuesGetAll()
public List<Models.AnagKeyValueModel> AnagKeyValuesGetAll()
{
List<Models.AnagKeyValue> dbResult = new List<Models.AnagKeyValue>();
List<Models.AnagKeyValueModel> dbResult = new List<Models.AnagKeyValueModel>();
using (MoonProContext localDbCtx = new MoonProContext(_configuration))
{
dbResult = localDbCtx
+5 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -23,4 +23,8 @@
<PackageReference Include="NLog" Version="4.7.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Egw.Core\Egw.Core.csproj" />
</ItemGroup>
</Project>
@@ -11,7 +11,7 @@ namespace MP.AppAuth.Models
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
[Table("AnagKeyValue")]
public partial class AnagKeyValue
public partial class AnagKeyValueModel
{
#region Public Properties
+2 -2
View File
@@ -63,7 +63,7 @@ namespace MP.AppAuth
public virtual DbSet<AnagraficaOperatori> AnagraficaOperatoris { get; set; }
public virtual DbSet<Config> Configs { get; set; }
public virtual DbSet<DatiMacchine> DatiMacchines { get; set; }
public virtual DbSet<AnagKeyValue> DbSetAnagKeyValues { get; set; }
public virtual DbSet<AnagKeyValueModel> DbSetAnagKeyValues { get; set; }
public virtual DbSet<FamigliaTipoIngressi> FamigliaTipoIngressis { get; set; }
public virtual DbSet<FamiglieMacchine> FamiglieMacchines { get; set; }
public virtual DbSet<KeepAlive> KeepAlives { get; set; }
@@ -151,7 +151,7 @@ namespace MP.AppAuth
entity.Property(e => e.Descrizione).HasMaxLength(500);
});
modelBuilder.Entity<AnagKeyValue>(entity =>
modelBuilder.Entity<AnagKeyValueModel>(entity =>
{
entity.HasKey(e => e.NomeVar);
+55 -3
View File
@@ -3,8 +3,8 @@
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@inject AppAuthService DataService
@inject LicenseService LicServ
<div class="card">
<div class="card-header">
@@ -65,10 +65,62 @@
[Parameter]
public UpdMan CurrItem { get; set; }
protected List<AnagKeyValueModel> AKVList
{
get
{
return LicServ.AKVList;
}
set
{
LicServ.AKVList = value;
}
}
protected override async Task OnInitializedAsync()
{
// check init AKV
if (AKVList == null || AKVList.Count == 0)
{
AKVList = await DataService.AnagKeyValList();
LicServ.InitAkv();
}
}
protected string getAKVString(string nomeVar)
{
string answ = "";
if (AKVList != null)
{
var currRec = AKVList.FirstOrDefault(x => x.NomeVar == nomeVar);
if (currRec != null)
{
answ = currRec.ValString;
}
}
return answ;
}
protected AnagKeyValueModel getAKVRec(string nomeVar)
{
AnagKeyValueModel answ = new AnagKeyValueModel();
if (AKVList != null)
{
answ = AKVList.FirstOrDefault(x => x.NomeVar == nomeVar);
}
return answ;
}
protected bool authOk()
{
bool answ = !string.IsNullOrEmpty(CurrItem.LicenseKey) && CurrItem.IsAuth;
return answ;
bool allOk = !string.IsNullOrEmpty(CurrItem.LicenseKey);
if (allOk)
{
allOk = LicServ.checkLicenseActive(CurrItem.LicenseKey);
}
return allOk;
}
protected string fullUrl(string relUrl)
+4 -1
View File
@@ -1,4 +1,7 @@
<div class="row text-center">
@using MP.Land.Data
@inject LicenseService LicServ
<div class="row text-center">
@if (authOk())
{
<div class="col-12 mt-2">
+5 -1
View File
@@ -42,7 +42,11 @@ namespace MP.Land.Components
protected bool authOk()
{
bool answ = !string.IsNullOrEmpty(CurrItem.LicenseKey) && CurrItem.IsAuth;
bool answ = !string.IsNullOrEmpty(CurrItem.LicenseKey);
if (answ)
{
answ = LicServ.checkLicenseActive(CurrItem.LicenseKey);
}
return answ;
}
+8 -2
View File
@@ -173,9 +173,9 @@ namespace MP.Land.Data
return await Task.FromResult(dbResult);
}
public async Task<List<AppAuth.Models.AnagKeyValue>> AnagKeyValList()
public async Task<List<AppAuth.Models.AnagKeyValueModel>> AnagKeyValList()
{
List<AppAuth.Models.AnagKeyValue> dbResult = new List<AppAuth.Models.AnagKeyValue>();
List<AppAuth.Models.AnagKeyValueModel> dbResult = new List<AppAuth.Models.AnagKeyValueModel>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = MpDbController.AnagKeyValuesGetAll();
@@ -185,6 +185,12 @@ namespace MP.Land.Data
return await Task.FromResult(dbResult);
}
public async Task ResetCache()
{
string cacheKey = ":MP:VOCAB";
await distributedCache.RemoveAsync(cacheKey);
}
#endregion Public Methods
}
}
+367
View File
@@ -0,0 +1,367 @@
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;
namespace MP.Land.Data
{
/// <summary>
/// Servizi e dati condivisi a livello applicazione
/// </summary>
public class LicenseService
{
#region Private Fields
private static IConfiguration? _configuration;
private static ILogger<LicenseService>? _logger;
/// <summary>
/// URL dell'API x chiamate gestione licenze
/// </summary>
private static string apiUrl = "https://liman.egalware.com/ELM.API/";
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 Protected Fields
/// <summary>
/// Chiave redis x attivazioni della licenza
/// </summary>
protected const string rKeyAttByLic = "LongCache:AttByLic";
#endregion Protected Fields
#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);
public string Installazione { 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) && ActivList != null && ActivList.Count > 0;
return checkData;
}
}
#endregion Public 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);
}
private void ReportUpdated()
{
if (EA_InfoUpdated != null)
{
EA_InfoUpdated?.Invoke();
}
}
#endregion Private Methods
#region Protected Methods
/// <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 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>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public bool InitAkv()
{
bool fatto = false;
Installazione = getAVKStr("Installazione");
MasterKey = getAVKStr(Applicazione);
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
return fatto;
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public async Task<bool> 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;
}
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;
}
/// <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)
{
numLic = (int)recLic.ValInt;
// verifico scadenza licenza!
DateTime scadenza = licenseManGLS.expiryDateByAuthKey(Installazione, recLic.NomeVar, numLic, authKey);
answ = scadenza > DateTime.Today;
}
else
{
_logger.LogInformation($"Record non trovato per {authKey}");
}
}
return answ;
}
#endregion Public Methods
}
}
+3 -2
View File
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Land</RootNamespace>
<Version>6.14.2112.2315</Version>
<Version>6.14.2202.0112</Version>
</PropertyGroup>
<ItemGroup>
@@ -49,6 +49,7 @@
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="RestSharp" Version="107.1.2" />
</ItemGroup>
<ItemGroup>
+29
View File
@@ -0,0 +1,29 @@
@page "/RefreshData"
@using MP.Land.Components
@using MP.Land.Data
@inject AppAuthService DataService
@inject LicenseService LicServ
@inject NavigationManager NavManager
<div class="card">
<div class="card-body">
<LoadingData></LoadingData>
</div>
</div>
@code {
protected override async Task OnInitializedAsync()
{
await Task.Delay(100);
LicServ.AKVList = new List<AppAuth.Models.AnagKeyValueModel>();
await Task.Delay(100);
await DataService.ResetCache();
await Task.Delay(100);
// redireziono
NavManager.NavigateTo("");
}
}
+1
View File
@@ -2,6 +2,7 @@
@using MP.Land.Data
@using MP.Land.Components
@inject LicenseService LicServ
<div class="alert alert-secondary">
<div class="row">
+12 -2
View File
@@ -88,8 +88,18 @@ namespace MP.Land.Pages
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// ciclo su tutti quelli con licenza valida...
var authList = ListRecords
.Where(x => !string.IsNullOrEmpty(x.LicenseKey) && x.IsAuth).ToList();
List<AppAuth.Models.UpdMan> rawList = ListRecords
.Where(x => !string.IsNullOrEmpty(x.LicenseKey)).ToList();
List<AppAuth.Models.UpdMan> authList = new List<AppAuth.Models.UpdMan>();
// ciclo SOLO tra quelli davvero autorizzati...
foreach (var item in rawList)
{
if (LicServ.checkLicenseActive(item.LicenseKey))
{
authList.Add(item);
}
}
numTot = authList.Count;
foreach (var item in authList)
{
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo gestione Programmi MAPO</i>
<h4>Versione: 6.14.2112.2315</h4>
<h4>Versione: 6.14.2202.0112</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.14.2112.2315
6.14.2202.0112
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.14.2112.2315</version>
<version>6.14.2202.0112</version>
<url>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+5
View File
@@ -42,6 +42,11 @@
<span class="fas fa-wrench fa-2x pr-2" aria-hidden="true"></span> System Info
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="RefreshData">
<span class="fas fa-sync-alt fa-2x pr-2" aria-hidden="true"></span> Refresh Data
</NavLink>
</li>
</ul>
</div>
+1
View File
@@ -116,6 +116,7 @@ namespace MP.Land
services.AddServerSideBlazor();
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<LicenseService>();
services.AddScoped<AppAuthService>();
services.AddScoped<MessageService>();
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>MP.Prog</RootNamespace>
<Version>6.14.2110.1510</Version>
<Version>6.14.2112.2315</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo gestione Programmi MAPO</i>
<h4>Versione: 6.14.2110.1510</h4>
<h4>Versione: 6.14.2112.2315</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.14.2110.1510
6.14.2112.2315
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.14.2110.1510</version>
<version>6.14.2112.2315</version>
<url>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/MP.Prog.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>MP.Stats</RootNamespace>
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
<Version>6.14.2109.3019</Version>
<Version>6.14.2201.1815</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo statistiche MAPO</i>
<h4>Versione: 6.14.2109.3019</h4>
<h4>Versione: 6.14.2201.1815</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.14.2109.3019
6.14.2201.1815
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.14.2109.3019</version>
<version>6.14.2201.1815</version>
<url>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>