Merge branch 'release/AddApiCallLog' into main

This commit is contained in:
Samuele E. Locatelli
2021-11-17 19:17:39 +01:00
36 changed files with 1320 additions and 143 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class SampleStats
{
public string Name { get; set; } = "NA";
public DateTime DtFirst { get; set; } = DateTime.Now;
public DateTime DtLast { get; set; } = DateTime.Now;
public List<string> VList { get; set; } = new List<string>();
}
}
+1
View File
@@ -14,6 +14,7 @@ namespace Core
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;
@@ -33,7 +33,7 @@ namespace LiMan.APi.Controllers
/// <param name="DataService"></param>
public ApplicazioneController(ApiDataService DataService)
{
_DataService = DataService;
dataService = DataService;
Log.Info("Avviata classe ApplicazioneController");
}
@@ -44,7 +44,7 @@ namespace LiMan.APi.Controllers
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected ApiDataService _DataService { get; set; }
protected ApiDataService dataService { get; set; }
#endregion Protected Properties
@@ -60,7 +60,8 @@ namespace LiMan.APi.Controllers
[HttpGet("{id}")]
public async Task<List<DB.DTO.ApplicativoDTO>> Get(string id, string CodApp)
{
var result = await _DataService.ApplicativiSearch(id, CodApp, true);
var result = await dataService.ApplicativiSearch(id, CodApp, true);
await dataService.recordCall(id, CodApp, $"GET:api/applicazione");
return result;
}
+35 -25
View File
@@ -34,7 +34,7 @@ namespace LiMan.APi.Controllers
/// <param name="DataService"></param>
public AttivazioniController(ApiDataService DataService)
{
_DataService = DataService;
dataService = DataService;
Log.Info("Avviata classe AttivazioniController");
}
@@ -45,7 +45,7 @@ namespace LiMan.APi.Controllers
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected ApiDataService _DataService { get; set; }
protected ApiDataService dataService { get; set; }
#endregion Protected Properties
@@ -58,7 +58,13 @@ namespace LiMan.APi.Controllers
[HttpDelete()]
public async Task<bool> Delete([FromBody] UserLicenseRequest CurrRequest)
{
bool done = await _DataService.AttivazioniDelete(CurrRequest.MasterKey, CurrRequest.ParamDict);
bool done = await dataService.AttivazioniDelete(CurrRequest.MasterKey, CurrRequest.ParamDict);
// se ho qualcosa da loggare...
foreach (var item in CurrRequest.ParamDict)
{
// registro 1 riga x ogni record...
await dataService.recordCall(CurrRequest.MasterKey, $"DELETE:api/attivazioni:{item.Key}|{item.Value}");
}
return done;
}
@@ -72,8 +78,9 @@ namespace LiMan.APi.Controllers
public async Task<List<DB.DTO.AttivazioneDTO>> Get(string chiave)
{
List<DB.DTO.AttivazioneDTO> result = new List<DB.DTO.AttivazioneDTO>();
var dbResult = await _DataService.AttivazioniByMasterKey(chiave, false);
var dbResult = await dataService.AttivazioniByMasterKey(chiave, false);
result = (dbResult != null) ? dbResult : result;
await dataService.recordCall(chiave, $"GET:api/attivazioni:{chiave}");
return result;
}
@@ -88,9 +95,14 @@ namespace LiMan.APi.Controllers
List<DB.DTO.AttivazioneDTO> currData = new List<DB.DTO.AttivazioneDTO>();
// eseguo tentativo generazione attivazioni da licenza...
bool done = await _DataService.AttivazioniTryAdd(CurrRequest.MasterKey, CurrRequest.ParamDict, 60);
currData = await _DataService.AttivazioniByMasterKey(CurrRequest.MasterKey, false);
bool done = await dataService.AttivazioniTryAdd(CurrRequest.MasterKey, CurrRequest.ParamDict, 60);
currData = await dataService.AttivazioniByMasterKey(CurrRequest.MasterKey, false);
// se ho qualcosa da loggare...
foreach (var item in CurrRequest.ParamDict)
{
// registro 1 riga x ogni record...
await dataService.recordCall(CurrRequest.MasterKey, $"POST:api/attivazioni:{item.Key}|{item.Value}");
}
return currData;
}
@@ -98,16 +110,21 @@ namespace LiMan.APi.Controllers
/// Richiesta di refresh delle key associate ai CodImpiego da una lista di chiavi di licenza sub
/// </summary>
/// <param name="CurrRequest">Obj Richiesta con licenza MASTER + Elenco codici impiego (key) + valori in formato dizionari</param>
// POST api/attivazioni
// POST api/attivazioni/refreshKey
[HttpPost("refreshKey")]
public async Task<List<DB.DTO.AttivazioneDTO>> refreshKey([FromBody] UserLicenseRequest CurrRequest)
{
List<DB.DTO.AttivazioneDTO> currData = new List<DB.DTO.AttivazioneDTO>();
// eseguo tentativo generazione attivazioni da licenza...
bool done = await _DataService.AttivazioniTryRefresh(CurrRequest.MasterKey, CurrRequest.ParamDict);
currData = await _DataService.AttivazioniByMasterKey(CurrRequest.MasterKey, false);
bool done = await dataService.AttivazioniTryRefresh(CurrRequest.MasterKey, CurrRequest.ParamDict);
currData = await dataService.AttivazioniByMasterKey(CurrRequest.MasterKey, false);
// se ho qualcosa da loggare...
foreach (var item in CurrRequest.ParamDict)
{
// registro 1 riga x ogni record...
await dataService.recordCall(CurrRequest.MasterKey, $"POST:api/attivazioni/refreshKey:{item.Key}__{item.Value}");
}
return currData;
}
@@ -115,11 +132,12 @@ namespace LiMan.APi.Controllers
/// Eliminazione di TUTTE le attivazioni SCADUTE
/// </summary>
/// <param name="chiave">Licenza MASTER</param>
// DELETE api/attivazioni/5
// DELETE api/attivazioni/resetAvail
[HttpDelete("resetAvail")]
public async Task<bool> ResetAvail(string chiave)
{
bool done = await _DataService.AttivazioniResetAvail(chiave);
bool done = await dataService.AttivazioniResetAvail(chiave);
await dataService.recordCall(chiave, $"DELETE:api/attivazioni/resetAvail:{chiave}");
return done;
}
@@ -127,27 +145,19 @@ namespace LiMan.APi.Controllers
/// Verifica recupero un record di sub licenza
/// </summary>
/// <param name="chiave">Licenza MASTER</param>
/// <param name="CodImpiego">Codice univoco impiego licenza</param>
/// <param name="codImpiego">Codice univoco impiego licenza</param>
/// <returns></returns>
// GET api/attivazioni/verifica/5
[HttpGet("verifica")]
public async Task<DB.DTO.AttivazioneDTO> VerificaImpiego(string chiave, string CodImpiego)
public async Task<DB.DTO.AttivazioneDTO> VerificaImpiego(string chiave, string codImpiego)
{
DB.DTO.AttivazioneDTO result = new DB.DTO.AttivazioneDTO();
var dbResult = await _DataService.AttivazioneSearch(chiave, CodImpiego, false);
var dbResult = await dataService.AttivazioneSearch(chiave, codImpiego, false);
result = (dbResult != null) ? dbResult : result;
await dataService.recordCall(chiave, $"GET:api/attivazioni/verifica:{chiave}__{codImpiego}");
return result;
}
#endregion Public Methods
#if false
// PUT api/attivazioni/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
#endif
}
}
@@ -33,7 +33,7 @@ namespace LiMan.APi.Controllers
/// <param name="DataService"></param>
public InstallazioniController(ApiDataService DataService)
{
_DataService = DataService;
dataService = DataService;
Log.Info("Avviata classe InstallazioniController");
}
@@ -44,7 +44,7 @@ namespace LiMan.APi.Controllers
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected ApiDataService _DataService { get; set; }
protected ApiDataService dataService { get; set; }
#endregion Protected Properties
@@ -59,9 +59,9 @@ namespace LiMan.APi.Controllers
[HttpGet("{id}")]
public async Task<List<string>> Get(string id)
{
var result = await _DataService.LicenzeByCliente(id);
var result = await dataService.LicenzeByCliente(id);
var listaApp = result.Select(x => x.CodApp).ToList();
await dataService.recordCall(id, "*", "GET:api/installazioni");
return listaApp;
}
+9 -8
View File
@@ -34,7 +34,7 @@ namespace LiMan.APi.Controllers
/// <param name="DataService"></param>
public LicenzaController(ApiDataService DataService)
{
_DataService = DataService;
dataService = DataService;
Log.Info("Avviata classe LicenzaController");
}
@@ -45,7 +45,7 @@ namespace LiMan.APi.Controllers
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected ApiDataService _DataService { get; set; }
protected ApiDataService dataService { get; set; }
#endregion Protected Properties
@@ -62,8 +62,8 @@ namespace LiMan.APi.Controllers
[HttpGet("{id}")]
public async Task<List<DB.DTO.ApplicativoDTO>> Get(string id, string CodApp, string Chiave)
{
var result = await _DataService.LicenzeSearch(id, CodApp, Chiave, false);
var result = await dataService.LicenzeSearch(id, CodApp, Chiave, false);
await dataService.recordCall(id, CodApp, $"GET:api/licenza:{Chiave}");
return result;
}
@@ -76,20 +76,21 @@ namespace LiMan.APi.Controllers
[HttpPost()]
public async Task<List<DB.DTO.ApplicativoDTO>> Get([FromBody] LicenseCoord AppInfo)
{
var result = await _DataService.LicenzeSearch(AppInfo.CodInst, AppInfo.CodApp, AppInfo.MasterKey, false);
var result = await dataService.LicenzeSearch(AppInfo.CodInst, AppInfo.CodApp, AppInfo.MasterKey, false);
await dataService.recordCall(AppInfo.CodInst, AppInfo.CodApp, $"POST:api/licenza:{AppInfo.MasterKey}");
return result;
}
/// POST api/licenza/refreshPayload
/// <summary>
/// Effettua refresh del payload calcolato ed aggiorna record ed infine lo restituisce
/// </summary>
/// <param name="AppInfo">Info licenza in formato LicenseCoord</param>
// POST api/attivazioni/refreshPayload
[HttpPost("refreshPayload")]
public async Task<DB.DTO.ApplicativoDTO> RefreshPayload([FromBody] LicenseCoord AppInfo)
{
var done = await _DataService.LicenzaRefreshPayload(AppInfo);
var done = await dataService.LicenzaRefreshPayload(AppInfo);
await dataService.recordCall(AppInfo.CodInst, AppInfo.CodApp, $"POST:api/licenza/refreshPayload:{AppInfo.MasterKey}");
return done;
}
+7 -7
View File
@@ -34,7 +34,7 @@ namespace LiMan.APi.Controllers
/// <param name="DataService"></param>
public TicketController(ApiDataService DataService)
{
_DataService = DataService;
dataService = DataService;
Log.Info("Avviata classe TicketController");
}
@@ -45,7 +45,7 @@ namespace LiMan.APi.Controllers
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected ApiDataService _DataService { get; set; }
protected ApiDataService dataService { get; set; }
#endregion Protected Properties
@@ -62,8 +62,8 @@ namespace LiMan.APi.Controllers
[HttpGet("{id}")]
public async Task<List<DB.DBModels.TicketModel>> Get(string id, string CodApp, string Chiave)
{
var result = await _DataService.TicketByCliente(id, CodApp, Chiave);
var result = await dataService.TicketByCliente(id, CodApp, Chiave);
await dataService.recordCall(id, CodApp, $"GET:api/ticket:{Chiave}");
return result;
}
@@ -80,11 +80,11 @@ namespace LiMan.APi.Controllers
if (CurrRequest.IsValid)
{
// registro richiesta
var insRes = await _DataService.TicketAdd(CurrRequest);
var insRes = await dataService.TicketAdd(CurrRequest);
}
// restituisco richieste aperte
result = await _DataService.TicketByCliente(CurrRequest.CodInst, CurrRequest.CodApp, CurrRequest.MasterKey);
result = await dataService.TicketByCliente(CurrRequest.CodInst, CurrRequest.CodApp, CurrRequest.MasterKey);
await dataService.recordCall(CurrRequest.CodInst, CurrRequest.CodApp, $"POST:api/ticket/sendReq:{CurrRequest.MasterKey}");
return result;
}
+359 -26
View File
@@ -1,13 +1,19 @@
using Core;
using LiMan.DB.DBModels;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LiMan.DB.Enum;
using StackExchange.Redis.Extensions.Core.Abstractions;
namespace LiMan.APi.Data
{
@@ -16,21 +22,57 @@ namespace LiMan.APi.Data
/// </summary>
public class ApiDataService : IDisposable
{
#region Public Fields
/// <summary>
/// Classe Accesso metodi DB
/// </summary>
public static LiMan.DB.Controllers.DbController dbController;
#endregion Public Fields
#region Protected Fields
/// <summary>
/// TTL da 1 h x cache Redis
/// </summary>
protected const int hourTTL = 60 * 60;
/// <summary>
/// Chiave redis x statistiche in acquisizione
/// </summary>
protected const string rKeySampleStats = "LiMan.UI:SampleStats:Curr";
/// <summary>
/// Chiave redis x statistiche in acquisizione
/// </summary>
protected const string rKeySampleVars = "LiMan.UI:SampleStats:Vars";
#endregion Protected Fields
#region Private Fields
private static IConfiguration _configuration;
private static ILogger<ApiDataService> _logger;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
//private readonly IDistributedCache distributedCache;
private readonly IRedisCacheClient _redisCacheClient;
/// <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 * 2;
#endregion Private Fields
#region Public Fields
public static LiMan.DB.Controllers.DbController dbController;
#endregion Public Fields
#region Public Constructors
/// <summary>
@@ -38,10 +80,18 @@ namespace LiMan.APi.Data
/// </summary>
/// <param name="configuration"></param>
/// <param name="logger"></param>
public ApiDataService(IConfiguration configuration, ILogger<ApiDataService> logger)
/// <param name="distributedCache"></param>
/// <param name="emailSender"></param>
/// <param name="redisCacheClient"></param>
public ApiDataService(IConfiguration configuration, ILogger<ApiDataService> logger, IEmailSender emailSender, IRedisCacheClient redisCacheClient)
//public ApiDataService(IConfiguration configuration, ILogger<ApiDataService> logger, IDistributedCache distributedCache, IEmailSender emailSender, IRedisCacheClient redisCacheClient)
{
_logger = logger;
_configuration = configuration;
_emailSender = emailSender;
_redisCacheClient = redisCacheClient;
//this.distributedCache = distributedCache;
// conf DB
string connStrDB = _configuration.GetConnectionString("LiMan.DB");
if (string.IsNullOrEmpty(connStrDB))
@@ -57,24 +107,6 @@ namespace LiMan.APi.Data
#endregion Public Constructors
#region Internal Methods
/// <summary>
/// Effettua refresh del payload della licenza dato info + enigma generato dal client
/// </summary>
/// <param name="appInfo"></param>
/// <returns></returns>
internal async Task<DB.DTO.ApplicativoDTO> LicenzaRefreshPayload(LicenseCoord appInfo)
{
// chiamo metodo x ricalcolare payload dato enigma
bool done = await dbController.LicenseUpdatePayload(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, appInfo.Enigma);
// ora recupero i dati
var licList = await LicenzeSearch(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, false);
return licList.FirstOrDefault();
}
#endregion Internal Methods
#region Public Methods
/// <summary>
@@ -269,6 +301,71 @@ namespace LiMan.APi.Data
dbController.Dispose();
}
/// <summary>
/// Elenco licenze dato cliente
/// </summary>
/// <param name="chiave">Chiave Licenza x ricerca</param>
/// <returns></returns>
public async Task<LicenzaModel> LicenzaByMasterKey(string chiave)
{
LicenzaModel dbResult = new LicenzaModel();
string cacheKey = $"DATA:Licenze:ListByKey:{chiave}";
#if false
string rawData;
var redisDataList = await distributedCache.GetAsync(cacheKey);
if (redisDataList != null)
{
rawData = Encoding.UTF8.GetString(redisDataList);
dbResult = JsonConvert.DeserializeObject<LicenzaModel>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.LicenzaByKey(chiave);
rawData = JsonConvert.SerializeObject(dbResult);
redisDataList = Encoding.UTF8.GetBytes(rawData);
await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(5));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per LicenzaByMasterKey: {ts.TotalMilliseconds} ms");
}
#endif
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<LicenzaModel>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.LicenzaByKey(chiave);
rawData = JsonConvert.SerializeObject(dbResult);
await setRSV(cacheKey, rawData, hourTTL);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per LicenzaByMasterKey: {ts.TotalMilliseconds} ms");
}
return await Task.FromResult(dbResult);
}
/// <summary>
/// Effettua refresh del payload della licenza dato info + enigma generato dal client
/// </summary>
/// <param name="appInfo"></param>
/// <returns></returns>
public async Task<DB.DTO.ApplicativoDTO> LicenzaRefreshPayload(LicenseCoord appInfo)
{
// chiamo metodo x ricalcolare payload dato enigma
bool done = await dbController.LicenseUpdatePayload(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, appInfo.Enigma);
// ora recupero i dati
var licList = await LicenzeSearch(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, false);
return licList.FirstOrDefault();
}
/// <summary>
/// Elenco licenze dato cliente
/// </summary>
@@ -310,6 +407,101 @@ namespace LiMan.APi.Data
return await Task.FromResult(dbResult);
}
/// <summary>
/// Effettua registrazione chiamata verificando se vada messa sul DB o in redis...
/// </summary>
/// <param name="codInst"></param>
/// <param name="codApp"></param>
/// <param name="targetUrl"></param>
public async Task<bool> recordCall(string codInst, string codApp, string targetUrl)
{
bool fatto = false;
// in primis recupero statistiche (e nel mentre eventualmente salvo su DB)
SampleStats currStats = await getCurrStats();
// preparo chiave x dato da loggare
string currKey = $"{rKeySampleVars}:{codInst}:{codApp}:{targetUrl}";
// verifico presenza contatore corrente altrimenti aggiungo e salvo...
if (!currStats.VList.Contains(currKey))
{
currStats.VList.Add(currKey);
// salvo!
await setCurrStats(currStats);
}
// incremento valore contatore corrente
await redCountIncr(currKey);
return fatto;
}
/// <summary>
/// Effettua registrazione da codice chiave...
/// </summary>
/// <param name="chiave"></param>
/// <param name="targetUrl"></param>
public async Task<bool> recordCall(string chiave, string targetUrl)
{
// valutare se cache key --> lic...
var currLic = await LicenzaByMasterKey(chiave);
var fatto = await recordCall(currLic.CodInst, currLic.CodApp, targetUrl);
return fatto;
}
/// <summary>
/// Registro su DB le statistiche delle chiavi in elenco, resettando i vari contatori quando fatto
/// </summary>
/// <param name="keyList">Elenco key nel formato {rKeySampleVars}:{codInst}:{codApp}:{targetUrl}</param>
public async Task<bool> saveStatsToDb(List<string> keyList)
{
bool fatto = false;
// ciclo x eseguire 1:1
foreach (var item in keyList)
{
// scompongo key... senza url di base
string[] valStr = item.Replace($"{rKeySampleVars}:", "").Split(":");
if (valStr.Length > 2)
{
LogCallModel newRec = new LogCallModel()
{
CodInst = valStr[0],
CodApp = valStr[1],
TargetUrl = valStr[2],
DataRif = DateTime.Now,
NumCall = 1
};
fatto = await dbController.LogCallUpsert(newRec);
if (fatto)
{
await redCountClear(item);
}
}
}
return fatto;
}
/// <summary>
/// Invio email richiesta
/// </summary>
/// <param name="destEmail"></param>
/// <param name="oggetto"></param>
/// <param name="corpo"></param>
/// <returns></returns>
public async Task<bool> SendEmail(string destEmail, string oggetto, string corpo)
{
bool answ = false;
try
{
await _emailSender.SendEmailAsync(destEmail, oggetto, corpo);
answ = true;
}
catch
{ }
return answ;
}
/// <summary>
/// Esegue aggiunta Ticket richeisto + restitusice aperti x cliente
/// </summary>
@@ -376,6 +568,147 @@ namespace LiMan.APi.Data
#endregion Public Methods
#region Protected Methods
/// <summary>
/// Recupera statistiche correnti
/// </summary>
/// <returns></returns>
protected async Task<SampleStats> getCurrStats()
{
DateTime adesso = DateTime.Now;
SampleStats answ = new SampleStats()
{
Name = "ApiStats"
};
// in primis check data/ora prima/ultima scrittura del set... (2 date, lista chiavi gestite)
string rawData = await getRSV(rKeySampleStats);
if (rawData != null)
{
answ = JsonConvert.DeserializeObject<SampleStats>(rawData);
// aggiorno ultimo controllo e salvo...
answ.DtLast = adesso;
// salvo!
await setCurrStats(answ);
}
// controllo se scadute...
if (adesso.Subtract(answ.DtFirst).TotalMinutes > 60)
{
// se scaduto --> registrazione set sul DB (async), resettando i vari contatori...
bool salvato = await saveStatsToDb(answ.VList);
// inizio NUOVO set vuoto con record corrente
answ = new SampleStats()
{
Name = "ApiStats"
};
// salvo!
await setCurrStats(answ);
}
// restituisco record!
return answ;
}
/// <summary>
/// Recupero chiave da redis
/// </summary>
/// <param name="rKey"></param>
/// <returns></returns>
protected async Task<string> getRSV(string rKey)
{
string answ = await _redisCacheClient.GetDbFromConfiguration().GetAsync<string>(rKey);
return answ;
}
/// <summary>
/// Resetta contatore x la chiave redis indicata...
/// </summary>
/// <returns></returns>
protected async Task<bool> redCountClear(string rKey)
{
bool answ = false;
int currCount = 0;
answ = await setRSV(rKey, currCount, 2 * hourTTL);
return answ;
}
/// <summary>
/// Incrementa contatore x la chiave redis indicata...
/// </summary>
/// <returns></returns>
protected async Task<bool> redCountIncr(string rKey)
{
bool answ = false;
int currCount = 0;
string rawVal = await getRSV(rKey);
if (!string.IsNullOrEmpty(rawVal))
{
int.TryParse(rawVal, out currCount);
}
currCount++;
answ = await setRSV(rKey, currCount, 2 * hourTTL);
return answ;
}
/// <summary>
/// Salva statistiche correnti
/// </summary>
/// <returns></returns>
protected async Task<bool> setCurrStats(SampleStats newVal)
{
bool answ = false;
string rawData = JsonConvert.SerializeObject(newVal);
answ = await setRSV(rKeySampleStats, rawData, 24 * hourTTL);
return answ;
}
/// <summary>
/// Salvataggio chiave in redis
/// </summary>
/// <param name="rKey"></param>
/// <param name="rVal"></param>
/// <param name="ttlSec"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, string rVal, int ttlSec)
{
bool fatto = false;
await _redisCacheClient.GetDbFromConfiguration().AddAsync(rKey, rVal, DateTimeOffset.Now.AddSeconds(ttlSec));
fatto = true;
return fatto;
}
/// <summary>
/// Salvataggio chiave in redis
/// </summary>
/// <param name="rKey"></param>
/// <param name="rValInt"></param>
/// <param name="ttlSec"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, int rValInt, int ttlSec)
{
bool fatto = false;
await _redisCacheClient.GetDbFromConfiguration().AddAsync<int>(rKey, rValInt, DateTimeOffset.Now.AddSeconds(ttlSec));
fatto = true;
return fatto;
}
#endregion Protected Methods
#region Private Methods
/// <summary>
/// Parametri per generare opzioni cache
/// </summary>
/// <param name="multFact">Fattore di moltiplica cache (se 1 --> 2 e 5 min)</param>
/// <returns></returns>
private DistributedCacheEntryOptions cacheOpt(int multFact)
{
var numSecAbsExp = multFact <= 0 ? chAbsExp : chAbsExp * multFact;
var numSecSliExp = multFact <= 0 ? chSliExp : chSliExp * multFact;
return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddSeconds(numSecAbsExp)).SetSlidingExpiration(TimeSpan.FromSeconds(numSecSliExp));
}
#endregion Private Methods
#if false
/// <summary>
/// Elenco ticket dato licenza (limitato a maxRec)
+5 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -16,8 +16,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="StackExchange.Redis" Version="2.2.88" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="7.1.1" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="7.1.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
</ItemGroup>
+138 -10
View File
@@ -20,7 +20,7 @@
</summary>
<param name="DataService"></param>
</member>
<member name="P:LiMan.APi.Controllers.ApplicazioneController._DataService">
<member name="P:LiMan.APi.Controllers.ApplicazioneController.dataService">
<summary>
Dataservice x accesso DB
</summary>
@@ -50,7 +50,7 @@
</summary>
<param name="DataService"></param>
</member>
<member name="P:LiMan.APi.Controllers.AttivazioniController._DataService">
<member name="P:LiMan.APi.Controllers.AttivazioniController.dataService">
<summary>
Dataservice x accesso DB
</summary>
@@ -90,7 +90,7 @@
Verifica recupero un record di sub licenza
</summary>
<param name="chiave">Licenza MASTER</param>
<param name="CodImpiego">Codice univoco impiego licenza</param>
<param name="codImpiego">Codice univoco impiego licenza</param>
<returns></returns>
</member>
<member name="T:LiMan.APi.Controllers.InstallazioniController">
@@ -109,7 +109,7 @@
</summary>
<param name="DataService"></param>
</member>
<member name="P:LiMan.APi.Controllers.InstallazioniController._DataService">
<member name="P:LiMan.APi.Controllers.InstallazioniController.dataService">
<summary>
Dataservice x accesso DB
</summary>
@@ -138,7 +138,7 @@
</summary>
<param name="DataService"></param>
</member>
<member name="P:LiMan.APi.Controllers.LicenzaController._DataService">
<member name="P:LiMan.APi.Controllers.LicenzaController.dataService">
<summary>
Dataservice x accesso DB
</summary>
@@ -162,6 +162,7 @@
<returns></returns>
</member>
<member name="M:LiMan.APi.Controllers.LicenzaController.RefreshPayload(Core.LicenseCoord)">
POST api/licenza/refreshPayload
<summary>
Effettua refresh del payload calcolato ed aggiorna record ed infine lo restituisce
</summary>
@@ -183,7 +184,7 @@
</summary>
<param name="DataService"></param>
</member>
<member name="P:LiMan.APi.Controllers.TicketController._DataService">
<member name="P:LiMan.APi.Controllers.TicketController.dataService">
<summary>
Dataservice x accesso DB
</summary>
@@ -209,18 +210,62 @@
Classe astrazione accesso dati
</summary>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.#ctor(Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Logging.ILogger{LiMan.APi.Data.ApiDataService})">
<member name="F:LiMan.APi.Data.ApiDataService.chAbsExp">
<summary>
Durata assoluta massima della cache IN SECONDI
</summary>
</member>
<member name="F:LiMan.APi.Data.ApiDataService.chSliExp">
<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>
</member>
<member name="F:LiMan.APi.Data.ApiDataService.dbController">
<summary>
Classe Accesso metodi DB
</summary>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.getRSV(System.String)">
<summary>
Recupero chiave da redis
</summary>
<param name="rKey"></param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.setRSV(System.String,System.String,System.Int32)">
<summary>
Salvataggio chiave in redis
</summary>
<param name="rKey"></param>
<param name="rVal"></param>
<param name="ttlSec"></param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.setRSV(System.String,System.Int32,System.Int32)">
<summary>
Salvataggio chiave in redis
</summary>
<param name="rKey"></param>
<param name="rValInt"></param>
<param name="ttlSec"></param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.#ctor(Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Logging.ILogger{LiMan.APi.Data.ApiDataService},Microsoft.AspNetCore.Identity.UI.Services.IEmailSender,StackExchange.Redis.Extensions.Core.Abstractions.IRedisCacheClient)">
<summary>
Init classe
</summary>
<param name="configuration"></param>
<param name="logger"></param>
<param name="distributedCache"></param>
<param name="emailSender"></param>
<param name="redisCacheClient"></param>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.LicenzaRefreshPayload(Core.LicenseCoord)">
<member name="M:LiMan.APi.Data.ApiDataService.cacheOpt(System.Int32)">
<summary>
Effettua refresh del payload della licenza dato info + enigma generato dal client
Parametri per generare opzioni cache
</summary>
<param name="appInfo"></param>
<param name="multFact">Fattore di moltiplica cache (se 1 --> 2 e 5 min)</param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.ApplicativiSearch(System.String,System.String,System.Boolean)">
@@ -296,6 +341,20 @@
Dispose classe
</summary>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.LicenzaByMasterKey(System.String)">
<summary>
Elenco licenze dato cliente
</summary>
<param name="chiave">Chiave Licenza x ricerca</param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.LicenzaRefreshPayload(Core.LicenseCoord)">
<summary>
Effettua refresh del payload della licenza dato info + enigma generato dal client
</summary>
<param name="appInfo"></param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.LicenzeByCliente(System.String)">
<summary>
Elenco licenze dato cliente
@@ -313,6 +372,75 @@
<param name="HideData">Indica se nascondere i dati sensibili</param>
<returns></returns>
</member>
<member name="F:LiMan.APi.Data.ApiDataService.rKeySampleStats">
<summary>
Chiave redis x statistiche in acquisizione
</summary>
</member>
<member name="F:LiMan.APi.Data.ApiDataService.rKeySampleVars">
<summary>
Chiave redis x statistiche in acquisizione
</summary>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.getCurrStats">
<summary>
Recupera statistiche correnti
</summary>
<returns></returns>
</member>
<member name="F:LiMan.APi.Data.ApiDataService.hourTTL">
<summary>
TTL da 1 h x cache Redis
</summary>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.setCurrStats(Core.SampleStats)">
<summary>
Salva statistiche correnti
</summary>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.redCountIncr(System.String)">
<summary>
Incrementa contatore x la chiave redis indicata...
</summary>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.redCountClear(System.String)">
<summary>
Resetta contatore x la chiave redis indicata...
</summary>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.recordCall(System.String,System.String,System.String)">
<summary>
Effettua registrazione chiamata verificando se vada messa sul DB o in redis...
</summary>
<param name="codInst"></param>
<param name="codApp"></param>
<param name="targetUrl"></param>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.saveStatsToDb(System.Collections.Generic.List{System.String})">
<summary>
Registro su DB le statistiche delle chiavi in elenco, resettando i vari contatori quando fatto
</summary>
<param name="keyList">Elenco key nel formato {rKeySampleVars}:{codInst}:{codApp}:{targetUrl}</param>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.recordCall(System.String,System.String)">
<summary>
Effettua registrazione da codice chiave...
</summary>
<param name="chiave"></param>
<param name="targetUrl"></param>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.SendEmail(System.String,System.String,System.String)">
<summary>
Invio email richiesta
</summary>
<param name="destEmail"></param>
<param name="oggetto"></param>
<param name="corpo"></param>
<returns></returns>
</member>
<member name="M:LiMan.APi.Data.ApiDataService.TicketAdd(Core.SupportRequest)">
<summary>
Esegue aggiunta Ticket richeisto + restitusice aperti x cliente
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
@@ -22,7 +22,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
+26 -6
View File
@@ -1,19 +1,17 @@
using LiMan.APi.Data;
using LiMan.DB;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using StackExchange.Redis.Extensions.Core.Configuration;
using StackExchange.Redis.Extensions.Newtonsoft;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace LiMan.Serv
{
@@ -77,6 +75,28 @@ namespace LiMan.Serv
c.IncludeXmlComments(xmlPath);
});
// abilitazione x email management con MailKit
services.AddTransient<IEmailSender, MailKitEmailSender>();
services.Configure<MailKitEmailSenderOptions>(options =>
{
options.Host_Address = Configuration["ExternalProviders:MailKit:SMTP:Address"];
options.Host_Port = Convert.ToInt32(Configuration["ExternalProviders:MailKit:SMTP:Port"]);
options.Host_Username = Configuration["ExternalProviders:MailKit:SMTP:Account"];
options.Host_Password = Configuration["ExternalProviders:MailKit:SMTP:Password"];
options.Sender_EMail = Configuration["ExternalProviders:MailKit:SMTP:SenderEmail"];
options.Sender_Name = Configuration["ExternalProviders:MailKit:SMTP:SenderName"];
});
//services.AddStackExchangeRedisCache(options =>
//{
// options.Configuration = Configuration.GetConnectionString("Redis");
//});
services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>((options) =>
{
return Configuration.GetSection("Redis").Get<RedisConfiguration>();
});
services.AddSingleton<ApiDataService>();
}
+42 -12
View File
@@ -1,15 +1,45 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"LiMan.GLS": "Server=SQLSTEAM;Database=SteamWare_Auth;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
"LiMan.DB": "Server=SQLSTEAM;Database=LiMan.DB;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
"Redis": "localhost:6379"
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"LiMan.GLS": "Server=SQLSTEAM;Database=SteamWare_Auth;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
"LiMan.DB": "Server=SQLSTEAM;Database=LiMan.DB;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
"Redis": "localhost:6379,DefaultDatabase=13"
},
"ExternalProviders": {
"MailKit": {
"SMTP": {
"Address": "smtp.gmail.com",
"Port": "465",
"Account": "steamwarebot@gmail.com",
"Password": "drmfsls16",
"SenderEmail": "steamwarebot@gmail.com",
"SenderName": "Steamware Email BOT"
}
}
},
"MailDest": {
"Admin": "samuele@steamware.net",
"ProcOp": "ceo@steamware.net"
},
"Redis": {
"Password": "",
"AllowAdmin": false,
"Ssl": false,
"ConnectTimeout": 6000,
"ConnectRetry": 2,
"Hosts": [
{
"Host": "localhost",
"Port": "6379"
}
],
"Database": 14
}
}
+75 -1
View File
@@ -53,7 +53,7 @@ namespace LiMan.DB.Controllers
// calcolo DTO Attivazione
var itemsTgt = localDbCtx
.DbSetSubLicenze
.Where(x => x.CodImpiego == item.Key && x.Chiave == item.Value && x.LicenzaNav.Chiave == MasterKey && x.VetoUnlock < oggi)
.Where(x => x.CodImpiego == item.Key && x.Chiave == item.Value && x.LicenzaNav.Chiave == MasterKey && x.VetoUnlock <= oggi)
.ToList();
// se trovate aggiungo ad elenco...
if (itemsTgt != null && itemsTgt.Count > 0)
@@ -653,6 +653,80 @@ namespace LiMan.DB.Controllers
return Task.FromResult(fatto);
}
public LicenzaModel LicenzaByKey(string MasterKey)
{
LicenzaModel dbResult = new LicenzaModel();
using (LMDbContext localDbCtx = new LMDbContext(_configuration))
{
DateTime oggi = DateTime.Today;
dbResult = localDbCtx
.DbSetLicenze
.Where(x => x.Chiave == MasterKey)
.FirstOrDefault();
}
return dbResult;
}
/// <summary>
/// Elenco LOG chiamate all'API dato filtro + limite record
/// </summary>
/// <param name="CodApp"></param>
/// <param name="CodInst"></param>
/// <param name="DateMax"></param>
/// <param name="maxNumRec"></param>
/// <returns></returns>
public List<LogCallModel> LogCallGetFilt(string CodApp, string CodInst, DateTime DateMax, int maxNumRec = 360)
{
List<LogCallModel> dbResult = new List<LogCallModel>();
using (LMDbContext localDbCtx = new LMDbContext(_configuration))
{
// recupero lista...
dbResult = localDbCtx
.DbSetLogCall
.Where(x => x.CodApp == CodApp && x.CodInst == CodInst && x.DataRif <= DateMax)
.OrderByDescending(x => x.DataRif)
.Take(maxNumRec)
.ToList();
}
return dbResult;
}
/// <summary>
/// Update/insert record Loc chiamate API
/// </summary>
/// <param name="currRequest"></param>
/// <returns></returns>
public async Task<bool> LogCallUpsert(LogCallModel currRequest)
{
bool fatto = false;
using (LMDbContext localDbCtx = new LMDbContext(_configuration))
{
// cerco record esistente...
var currRec = localDbCtx
.DbSetLogCall
.Where(x => x.CodApp == currRequest.CodApp && x.CodInst == currRequest.CodInst && x.DataRif == currRequest.DataRif && x.TargetUrl == currRequest.TargetUrl)
.FirstOrDefault();
if (currRec != null)
{
// se trovo aggiorno
currRec.NumCall = currRequest.NumCall;
}
else
{
//altrimenti aggiungo
localDbCtx
.DbSetLogCall
.Add(currRequest);
}
// salvo
await localDbCtx.SaveChangesAsync();
fatto = true;
}
return fatto;
}
/// <summary>
/// Annulla modifiche su una specifica entity (cancel update)
/// </summary>
+29
View File
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using static LiMan.DB.Enum;
#nullable disable
namespace LiMan.DB.DBModels
{
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
//[Index(nameof(Installazione), nameof(Active), nameof(DiskStatus))]
[Table("LogCall")]
public partial class LogCallModel
{
#region Public Properties
public DateTime DataRif { get; set; }
public string CodInst { get; set; }
public string CodApp { get; set; }
public string TargetUrl { get; set; }
public int NumCall { get; set; } = 0;
#endregion Public Properties
}
}
+7 -8
View File
@@ -49,23 +49,17 @@ namespace LiMan.DB
#region Public Properties
public virtual DbSet<ApplicativoModel> DbSetApp { get; set; }
public virtual DbSet<InstallazioneModel> DbSetInst { get; set; }
public virtual DbSet<LicenzaModel> DbSetLicenze { get; set; }
public virtual DbSet<LogCallModel> DbSetLogCall { get; set; }
public virtual DbSet<LogLicenzaModel> DbSetLogLicenze { get; set; }
public virtual DbSet<SubLicenzaModel> DbSetSubLicenze { get; set; }
public virtual DbSet<TicketModel> DbSetTicket { get; set; }
#endregion Public Properties
#region Private Methods
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
#endregion Private Methods
#region Protected Methods
@@ -89,6 +83,11 @@ namespace LiMan.DB
{
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<LogCallModel>(entity =>
{
entity.HasKey(e => new { e.DataRif, e.CodInst, e.CodApp, e.TargetUrl });
});
OnModelCreatingPartial(modelBuilder);
}
+4 -5
View File
@@ -1,14 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="2.15.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.10" />
+65
View File
@@ -0,0 +1,65 @@
using MailKit.Net.Smtp;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using MimeKit;
using MimeKit.Text;
using System.Threading.Tasks;
namespace LiMan.DB
{
/// <summary>
/// Implementazione interfaccia email con pacchetto MailKIT
///
/// https://www.ryadel.com/en/asp-net-core-send-email-messages-smtp-mailkit/
/// </summary>
public class MailKitEmailSender : IEmailSender
{
#region Public Constructors
public MailKitEmailSender(IOptions<MailKitEmailSenderOptions> options)
{
this.Options = options.Value;
}
#endregion Public Constructors
#region Public Properties
public MailKitEmailSenderOptions Options { get; set; }
#endregion Public Properties
#region Public Methods
public Task Execute(string to, string subject, string message)
{
// create message
var email = new MimeMessage();
email.Sender = MailboxAddress.Parse(Options.Sender_EMail);
if (!string.IsNullOrEmpty(Options.Sender_Name))
email.Sender.Name = Options.Sender_Name;
email.From.Add(email.Sender);
email.To.Add(MailboxAddress.Parse(to));
email.Subject = subject;
email.Body = new TextPart(TextFormat.Html) { Text = message };
// send email
using (var smtp = new SmtpClient())
{
smtp.Connect(Options.Host_Address, Options.Host_Port, Options.Host_SecureSocketOptions);
smtp.Authenticate(Options.Host_Username, Options.Host_Password);
smtp.Send(email);
smtp.Disconnect(true);
}
return Task.FromResult(true);
}
public Task SendEmailAsync(string email, string subject, string message)
{
return Execute(email, subject, message);
}
#endregion Public Methods
}
}
+36
View File
@@ -0,0 +1,36 @@
using MailKit.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LiMan.DB
{
public class MailKitEmailSenderOptions
{
#region Public Constructors
public MailKitEmailSenderOptions()
{
Host_SecureSocketOptions = SecureSocketOptions.Auto;
}
#endregion Public Constructors
#region Public Properties
public string Host_Address { get; set; }
public string Host_Password { get; set; }
public int Host_Port { get; set; }
public SecureSocketOptions Host_SecureSocketOptions { get; set; }
public string Host_Username { get; set; }
public string Sender_EMail { get; set; }
public string Sender_Name { get; set; }
#endregion Public Properties
}
}
+331
View File
@@ -0,0 +1,331 @@
// <auto-generated />
using System;
using LiMan.DB;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace LiMan.DB.Migrations
{
[DbContext(typeof(LMDbContext))]
[Migration("20211117101539_AddLogCalls")]
partial class AddLogCalls
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.10")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("LiMan.DB.DBModels.ApplicativoModel", b =>
{
b.Property<string>("CodApp")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Descrizione")
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("CodApp");
b.ToTable("Applicativi");
});
modelBuilder.Entity("LiMan.DB.DBModels.InstallazioneModel", b =>
{
b.Property<string>("CodInst")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Cliente")
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Contatto")
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Descrizione")
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Email")
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("CodInst");
b.ToTable("Installazioni");
});
modelBuilder.Entity("LiMan.DB.DBModels.LicenzaModel", b =>
{
b.Property<int>("IdxLic")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Chiave")
.HasColumnType("nvarchar(max)");
b.Property<string>("CodApp")
.HasColumnType("nvarchar(50)");
b.Property<string>("CodInst")
.HasColumnType("nvarchar(50)");
b.Property<DateTime>("DataEnigma")
.HasColumnType("datetime2");
b.Property<string>("Descrizione")
.HasColumnType("nvarchar(max)");
b.Property<string>("Enigma")
.HasColumnType("nvarchar(max)");
b.Property<bool>("Locked")
.HasColumnType("bit");
b.Property<int>("NumLicenze")
.HasColumnType("int");
b.Property<string>("Payload")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("Scadenza")
.HasColumnType("datetime2");
b.Property<int>("Tipo")
.HasColumnType("int");
b.HasKey("IdxLic");
b.HasIndex("CodApp");
b.HasIndex("CodInst");
b.ToTable("Licenze");
});
modelBuilder.Entity("LiMan.DB.DBModels.LogCallModel", b =>
{
b.Property<DateTime>("DataRif")
.HasColumnType("datetime2");
b.Property<string>("CodInst")
.HasColumnType("nvarchar(450)");
b.Property<string>("CodApp")
.HasColumnType("nvarchar(450)");
b.Property<string>("TargetUrl")
.HasColumnType("nvarchar(450)");
b.Property<int>("NumCall")
.HasColumnType("int");
b.HasKey("DataRif", "CodInst", "CodApp", "TargetUrl");
b.ToTable("LogCall");
});
modelBuilder.Entity("LiMan.DB.DBModels.LogLicenzaModel", b =>
{
b.Property<int>("IdxLogLic")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Chiave")
.HasColumnType("nvarchar(max)");
b.Property<string>("CodApp")
.HasColumnType("nvarchar(50)");
b.Property<string>("CodInst")
.HasColumnType("nvarchar(50)");
b.Property<string>("Descrizione")
.HasColumnType("nvarchar(max)");
b.Property<int>("IdxLic")
.HasColumnType("int");
b.Property<int>("NumLicenze")
.HasColumnType("int");
b.Property<DateTime>("Scadenza")
.HasColumnType("datetime2");
b.Property<int>("Tipo")
.HasColumnType("int");
b.HasKey("IdxLogLic");
b.HasIndex("CodApp");
b.HasIndex("CodInst");
b.HasIndex("IdxLic");
b.ToTable("LogLicenze");
});
modelBuilder.Entity("LiMan.DB.DBModels.SubLicenzaModel", b =>
{
b.Property<int>("IdxSubLic")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Chiave")
.HasColumnType("nvarchar(max)");
b.Property<string>("CodImpiego")
.HasColumnType("nvarchar(max)");
b.Property<int>("IdxLic")
.HasColumnType("int");
b.Property<int>("Tipo")
.HasColumnType("int");
b.Property<DateTime>("VetoUnlock")
.HasColumnType("datetime2");
b.HasKey("IdxSubLic");
b.HasIndex("IdxLic");
b.ToTable("SubLicenze");
});
modelBuilder.Entity("LiMan.DB.DBModels.TicketModel", b =>
{
b.Property<int>("IdxTicket")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("CodImpiego")
.HasColumnType("nvarchar(max)");
b.Property<string>("ContactEmail")
.HasColumnType("nvarchar(max)");
b.Property<string>("ContactName")
.HasColumnType("nvarchar(max)");
b.Property<string>("ContactPhone")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("DtReq")
.HasColumnType("datetime2");
b.Property<int>("IdxLic")
.HasColumnType("int");
b.Property<int>("IdxSubLic")
.HasColumnType("int");
b.Property<string>("ReqBody")
.HasColumnType("nvarchar(max)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("SupplAnsw")
.HasColumnType("nvarchar(max)");
b.Property<string>("SupplEmail")
.HasColumnType("nvarchar(max)");
b.Property<string>("SupplUserCode")
.HasColumnType("nvarchar(max)");
b.Property<int>("Tipo")
.HasColumnType("int");
b.HasKey("IdxTicket");
b.HasIndex("IdxLic");
b.ToTable("TicketLog");
});
modelBuilder.Entity("LiMan.DB.DBModels.LicenzaModel", b =>
{
b.HasOne("LiMan.DB.DBModels.ApplicativoModel", "ApplicativoNav")
.WithMany()
.HasForeignKey("CodApp");
b.HasOne("LiMan.DB.DBModels.InstallazioneModel", "InstallazioneNav")
.WithMany()
.HasForeignKey("CodInst");
b.Navigation("ApplicativoNav");
b.Navigation("InstallazioneNav");
});
modelBuilder.Entity("LiMan.DB.DBModels.LogLicenzaModel", b =>
{
b.HasOne("LiMan.DB.DBModels.ApplicativoModel", "ApplicativoNav")
.WithMany()
.HasForeignKey("CodApp");
b.HasOne("LiMan.DB.DBModels.InstallazioneModel", "InstallazioneNav")
.WithMany()
.HasForeignKey("CodInst");
b.HasOne("LiMan.DB.DBModels.LicenzaModel", "LicenzaNav")
.WithMany()
.HasForeignKey("IdxLic")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApplicativoNav");
b.Navigation("InstallazioneNav");
b.Navigation("LicenzaNav");
});
modelBuilder.Entity("LiMan.DB.DBModels.SubLicenzaModel", b =>
{
b.HasOne("LiMan.DB.DBModels.LicenzaModel", "LicenzaNav")
.WithMany("Attivazioni")
.HasForeignKey("IdxLic")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("LicenzaNav");
});
modelBuilder.Entity("LiMan.DB.DBModels.TicketModel", b =>
{
b.HasOne("LiMan.DB.DBModels.LicenzaModel", "LicenzaNav")
.WithMany("Tickets")
.HasForeignKey("IdxLic")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("LicenzaNav");
});
modelBuilder.Entity("LiMan.DB.DBModels.LicenzaModel", b =>
{
b.Navigation("Attivazioni");
b.Navigation("Tickets");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,32 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace LiMan.DB.Migrations
{
public partial class AddLogCalls : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "LogCall",
columns: table => new
{
DataRif = table.Column<DateTime>(type: "datetime2", nullable: false),
CodInst = table.Column<string>(type: "nvarchar(450)", nullable: false),
CodApp = table.Column<string>(type: "nvarchar(450)", nullable: false),
TargetUrl = table.Column<string>(type: "nvarchar(450)", nullable: false),
NumCall = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_LogCall", x => new { x.DataRif, x.CodInst, x.CodApp, x.TargetUrl });
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "LogCall");
}
}
}
@@ -111,6 +111,28 @@ namespace LiMan.DB.Migrations
b.ToTable("Licenze");
});
modelBuilder.Entity("LiMan.DB.DBModels.LogCallModel", b =>
{
b.Property<DateTime>("DataRif")
.HasColumnType("datetime2");
b.Property<string>("CodInst")
.HasColumnType("nvarchar(450)");
b.Property<string>("CodApp")
.HasColumnType("nvarchar(450)");
b.Property<string>("TargetUrl")
.HasColumnType("nvarchar(450)");
b.Property<int>("NumCall")
.HasColumnType("int");
b.HasKey("DataRif", "CodInst", "CodApp", "TargetUrl");
b.ToTable("LogCall");
});
modelBuilder.Entity("LiMan.DB.DBModels.LogLicenzaModel", b =>
{
b.Property<int>("IdxLogLic")
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
+18 -2
View File
@@ -11,6 +11,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LiMan.DB.Enum;
using Microsoft.AspNetCore.Identity.UI.Services;
namespace LiMan.UI.Data
{
@@ -20,8 +21,8 @@ namespace LiMan.UI.Data
private static IConfiguration _configuration;
private static ILogger<LiManDataService> _logger;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
private readonly IDistributedCache distributedCache;
private readonly IMemoryCache memoryCache;
@@ -54,10 +55,11 @@ namespace LiMan.UI.Data
#region Public Constructors
public LiManDataService(IConfiguration configuration, ILogger<LiManDataService> logger, IMemoryCache memoryCache, IDistributedCache distributedCache)
public LiManDataService(IConfiguration configuration, ILogger<LiManDataService> logger, IMemoryCache memoryCache, IDistributedCache distributedCache, IEmailSender emailSender)
{
_logger = logger;
_configuration = configuration;
_emailSender = emailSender;
// conf cache
this.memoryCache = memoryCache;
this.distributedCache = distributedCache;
@@ -547,6 +549,20 @@ namespace LiMan.UI.Data
dbControllerGLS.rollBackEntity(item);
}
public async Task<bool> SendEmail(string destEmail, string oggetto, string corpo)
{
bool answ = false;
try
{
await _emailSender.SendEmailAsync(destEmail, oggetto, corpo);
answ = true;
}
catch
{ }
return answ;
}
/// <summary>
/// Aggiornamentos tato ticket
/// </summary>
+2 -2
View File
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>1.1.2111.1618</Version>
<TargetFramework>net5.0</TargetFramework>
<Version>1.1.2111.1719</Version>
<RootNamespace>LiMan.UI</RootNamespace>
<AssemblyName>LiMan.UI</AssemblyName>
</PropertyGroup>
@@ -22,7 +22,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
@@ -22,7 +22,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
@@ -22,7 +22,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>License Manager</i>
<h4>Versione: 1.1.2111.1618</h4>
<h4>Versione: 1.1.2111.1719</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
1.1.2111.1618
1.1.2111.1719
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.1.2111.1618</version>
<version>1.1.2111.1719</version>
<url>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/LiMan.UI.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+14
View File
@@ -1,3 +1,4 @@
using LiMan.DB;
using LiMan.UI.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
@@ -13,6 +14,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.UI.Services;
namespace LiMan.UI
{
@@ -97,6 +99,18 @@ namespace LiMan.UI
options.InstanceName = "LiMan";
});
// abilitazione x email management con MailKit
services.AddTransient<IEmailSender, MailKitEmailSender>();
services.Configure<MailKitEmailSenderOptions>(options =>
{
options.Host_Address = Configuration["ExternalProviders:MailKit:SMTP:Address"];
options.Host_Port = Convert.ToInt32(Configuration["ExternalProviders:MailKit:SMTP:Port"]);
options.Host_Username = Configuration["ExternalProviders:MailKit:SMTP:Account"];
options.Host_Password = Configuration["ExternalProviders:MailKit:SMTP:Password"];
options.Sender_EMail = Configuration["ExternalProviders:MailKit:SMTP:SenderEmail"];
options.Sender_Name = Configuration["ExternalProviders:MailKit:SMTP:SenderName"];
});
services.AddLocalization();
services.AddRazorPages();
+28 -12
View File
@@ -1,15 +1,31 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"LiMan.GLS": "Server=SQLSTEAM;Database=SteamWare_Auth;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.UI;",
"LiMan.DB": "Server=SQLSTEAM;Database=LiMan.DB;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.UI;",
"Redis": "localhost:6379"
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"LiMan.GLS": "Server=SQLSTEAM;Database=SteamWare_Auth;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.UI;",
"LiMan.DB": "Server=SQLSTEAM;Database=LiMan.DB;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.UI;",
"Redis": "localhost:6379"
},
"ExternalProviders": {
"MailKit": {
"SMTP": {
"Address": "smtp.gmail.com",
"Port": "465",
"Account": "steamwarebot@gmail.com",
"Password": "drmfsls16",
"SenderEmail": "steamwarebot@gmail.com",
"SenderName": "Steamware Email BOT"
}
}
},
"MailDest": {
"Admin": "samuele@steamware.net",
"ProcOp": "ceo@steamware.net"
}
}