diff --git a/MP.Data/DTO/OperatoreDTO.cs b/MP.Data/DTO/OperatoreDTO.cs new file mode 100644 index 00000000..62f6e001 --- /dev/null +++ b/MP.Data/DTO/OperatoreDTO.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MP.Data.DTO +{ + public class OperatoreDTO + { + public int MatrOpr { get; set; } = 0; + public string Cognome { get; set; } = ""; + public string Nome { get; set; } = ""; + public bool isAdmin { get; set; } = false; + public string authKey { get; set; } = ""; + public string CodOprExt { get; set; } = ""; + public string userJWT { get; set; } = ""; + } +} diff --git a/MP.INVE/Components/CmpTop.razor b/MP.INVE/Components/CmpTop.razor index c2578ed2..214509c9 100644 --- a/MP.INVE/Components/CmpTop.razor +++ b/MP.INVE/Components/CmpTop.razor @@ -7,6 +7,7 @@
+ @userName
diff --git a/MP.INVE/Components/CmpTop.razor.cs b/MP.INVE/Components/CmpTop.razor.cs index 0fc621ce..88979cd7 100644 --- a/MP.INVE/Components/CmpTop.razor.cs +++ b/MP.INVE/Components/CmpTop.razor.cs @@ -1,11 +1,12 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.Configuration; using Microsoft.JSInterop; using MP.INVE.Data; namespace MP.INVE.Components { - public partial class CmpTop + public partial class CmpTop:IDisposable { #region Public Methods @@ -17,6 +18,13 @@ namespace MP.INVE.Components NavManager.NavigateTo(NavManager.Uri, true); } + public void Dispose() + { + LServ.EA_LogIn -= LServ_EA_LogIn; + LServ.EA_LogOut -= LServ_EA_LogOut; + GC.Collect(); + } + #endregion Public Methods #region Protected Properties @@ -24,20 +32,34 @@ namespace MP.INVE.Components [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; + [Inject] + protected LoginService LServ { get; set; } = null!; + #endregion Protected Properties #region Protected Methods protected override async Task OnInitializedAsync() { + LServ.EA_LogIn += LServ_EA_LogIn; + LServ.EA_LogOut += LServ_EA_LogOut; await forceReload(); } + private void LServ_EA_LogOut() + { + NavManager.NavigateTo("OperatoreLogin", true); + } + + private void LServ_EA_LogIn() + { + NavManager.NavigateTo("Starter", true); + } + #endregion Protected Methods #region Private Fields - private string userName = ""; #endregion Private Fields @@ -54,15 +76,27 @@ namespace MP.INVE.Components private async Task forceReload() { - var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - var user = authState.User; - if (user.Identity != null && user.Identity.IsAuthenticated) + await Task.Delay(1); + // controllo per login + if (LServ.matrOpr <= 0 && !NavManager.Uri.Contains("OperatoreLogin")) { - userName = $"{user.Identity.Name}"; + NavManager.NavigateTo("OperatoreLogin", true); } - else + } + + private async Task logOut() + { + await Task.Delay(1); + LServ.LogOut(); + } + + private string userName + { + get { - userName = "N.A."; + string answ = "ND"; + answ = $"{LServ.Cognome} {LServ.Cognome} ({LServ.matrOpr})"; + return answ; } } diff --git a/MP.INVE/Data/LoginService.cs b/MP.INVE/Data/LoginService.cs new file mode 100644 index 00000000..b76a8741 --- /dev/null +++ b/MP.INVE/Data/LoginService.cs @@ -0,0 +1,247 @@ +using MP.Data.DTO; +using Newtonsoft.Json; +using NLog; +using StackExchange.Redis; +using System.Diagnostics; + +namespace MP.INVE.Data +{ + public class LoginService : IDisposable + { + #region Public Constructors + + public LoginService(IConfiguration configuration, ILogger logger, HttpClient httpClient, + IHttpContextAccessor httpContextAccessor) + { + this.HttpClient = httpClient; + HttpContextAccessor = httpContextAccessor; + + _logger = logger; + _logger.LogInformation("Starting LoginService INIT"); + _configuration = configuration; + + // setup compoenti REDIS + redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis")); + redisConnAdmin = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("RedisAdmin")); + redisDb = redisConn.GetDatabase(); + + // leggo cache lungo periodo + int.TryParse(_configuration.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); + + _logger.LogInformation("Redis LoginService INIT"); + } + + #endregion Public Constructors + + #region Public Events + + public event Action EA_LogIn = null!; + + public event Action EA_LogOut = null!; + + #endregion Public Events + + #region Public Properties + + public string Cognome + { + get + { + string answ = "NA"; + if (matrOpr > 0 && !string.IsNullOrEmpty(authKey)) + { + var currUser = UserDTO(matrOpr, authKey); + if (currUser != null) + { + answ = currUser.Cognome; + } + } + return answ; + } + } + + public int matrOpr + { + get + { + int answ = 0; + if (HttpContextAccessor.HttpContext != null) + { + var token = HttpContextAccessor.HttpContext.Request.Cookies["userId_token"]; + if (token != null) + { + int.TryParse(token, out answ); + } + } + return answ; + } + set + { + CookieOptions options = new CookieOptions(); + options.Expires = DateTime.Now.AddDays(1); + if (HttpContextAccessor.HttpContext != null) + { + HttpContextAccessor.HttpContext.Response.Cookies.Append("userId_token", $"{value}", options); + } + } + } + + public string Nome + { + get + { + string answ = "NA"; + if (matrOpr > 0 && !string.IsNullOrEmpty(authKey)) + { + var currUser = UserDTO(matrOpr, authKey); + if (currUser != null) + { + answ = currUser.Nome; + } + } + return answ; + } + } + + #endregion Public Properties + + #region Public Methods + + public void Dispose() + { + } + + public void LogOut() + { + OperatoreDTO resetData = new OperatoreDTO(); + UserDTOSave(resetData); + } + + /// + /// Ricerca su REDIS dell'utente loggato + /// NB: da rifare con unico JWT che contenga tutto + /// + /// + /// + /// + public OperatoreDTO? UserDTO(int matrOpr, string authKey) + { + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + OperatoreDTO? result = null; + string source = "REDIS"; + // cerco in redis... + RedisValue rawData = redisDb.StringGet($"{redisUserSession}:{matrOpr}"); + if (!string.IsNullOrEmpty($"{rawData}")) + { + try + { + result = JsonConvert.DeserializeObject($"{rawData}"); + } + catch + { } + } +#if false + else + { + result = await Task.FromResult(dbController.AnagStatiComm()); + // serializzo e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(redisUserSession, rawData, getRandTOut(redisLongTimeCache)); + source = "DB"; + } +#endif + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Debug($"LoggedUser Read from {source}: {ts.TotalMilliseconds}ms"); + // restituisco + return result; + } + + /// + /// Salva su REDIS dati dell'utente loggato + /// + /// + public bool UserDTOSave(OperatoreDTO userData) + { + bool fatto = false; + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + string source = "REDIS"; + // cerco in redis... + string rawData = JsonConvert.SerializeObject(userData); + fatto = redisDb.StringSet($"{redisUserSession}:{userData.MatrOpr}", rawData, TimeSpan.FromMinutes(60)); + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Debug($"UserDTO write to {source}: {ts.TotalMilliseconds}ms"); + // restituisco + return fatto; + } + + #endregion Public Methods + + #region Protected Properties + + protected string authKey + { + get + { + string answ = ""; + if (HttpContextAccessor.HttpContext != null) + { + var token = HttpContextAccessor.HttpContext.Request.Cookies["authKey_token"]; + if (token != null) + { + answ = token; + } + } + return answ; + } + set + { + CookieOptions options = new CookieOptions(); + options.Expires = DateTime.Now.AddDays(1); + + if (HttpContextAccessor.HttpContext != null) + { + HttpContextAccessor.HttpContext.Response.Cookies.Append("authKey_token", value, options); + } + } + } + + protected HttpClient HttpClient { get; set; } + protected IHttpContextAccessor HttpContextAccessor { get; set; } + + #endregion Protected Properties + + #region Private Fields + + private const string redisBaseAddr = "MP:INVE"; + + private const string redisUserSession = redisBaseAddr + ":User:"; + private static IConfiguration _configuration = null!; + + private static ILogger _logger = null!; + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + /// + /// Oggetto per connessione a REDIS + /// + private ConnectionMultiplexer redisConn = null!; + + /// + /// Oggetto per connessione a REDIS modalità admin (ex flux dati) + /// + private ConnectionMultiplexer redisConnAdmin = null!; + + /// + /// Oggetto DB redis da impiegare x chiamate R/W + /// + private IDatabase redisDb = null!; + + private int redisLongTimeCache = 5; + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/MP.INVE/Data/MessageService.cs b/MP.INVE/Data/MessageService.cs index 99dc18df..985557d0 100644 --- a/MP.INVE/Data/MessageService.cs +++ b/MP.INVE/Data/MessageService.cs @@ -53,7 +53,7 @@ get => searchVal; set { - //if (searchVal != value) + //if (_nome != value) //{ searchVal = value; diff --git a/MP.INVE/Data/MpDataService.cs b/MP.INVE/Data/MpDataService.cs index 13c3ee36..e44df918 100644 --- a/MP.INVE/Data/MpDataService.cs +++ b/MP.INVE/Data/MpDataService.cs @@ -1090,37 +1090,37 @@ namespace MP.INVE.Data #region Private Fields - private const string redisArtByDossier = redisBaseAddr + "SPEC:Cache:ArtByDossier"; + private const string redisArtByDossier = redisBaseAddr + ":Cache:ArtByDossier"; - private const string redisArtList = redisBaseAddr + "SPEC:Cache:ArtList"; + private const string redisArtList = redisBaseAddr + ":Cache:ArtList"; - private const string redisBaseAddr = "MP:"; + private const string redisBaseAddr = "MP:SPEC"; - private const string redisConfKey = redisBaseAddr + "SPEC:Cache:Config"; + private const string redisConfKey = redisBaseAddr + ":Cache:Config"; - private const string redisDossByMac = redisBaseAddr + "SPEC:Cache:DossByMac"; + private const string redisDossByMac = redisBaseAddr + ":Cache:DossByMac"; - private const string redisFluxByMac = redisBaseAddr + "SPEC:Cache:FluxByMac"; + private const string redisFluxByMac = redisBaseAddr + ":Cache:FluxByMac"; - private const string redisFluxLogFilt = redisBaseAddr + "SPEC:Cache:FluxLogFilt"; + private const string redisFluxLogFilt = redisBaseAddr + ":Cache:FluxLogFilt"; - private const string redisMacByFlux = redisBaseAddr + "SPEC:Cache:MacByFlux"; + private const string redisMacByFlux = redisBaseAddr + ":Cache:MacByFlux"; - private const string redisMacList = redisBaseAddr + "SPEC:Cache:MacList"; + private const string redisMacList = redisBaseAddr + ":Cache:MacList"; - private const string redisOdlCurrByMac = redisBaseAddr + "SPEC:Cache:OdlByMac"; + private const string redisOdlCurrByMac = redisBaseAddr + ":Cache:OdlByMac"; - private const string redisPOdlList = redisBaseAddr + "SPEC:Cache:POdlList"; + private const string redisPOdlList = redisBaseAddr + ":Cache:POdlList"; - private const string redisPOdlByPOdl = redisBaseAddr + "SPEC:Cache:POdlByPOdl"; + private const string redisPOdlByPOdl = redisBaseAddr + ":Cache:POdlByPOdl"; - private const string redisPOdlByOdl = redisBaseAddr + "SPEC:Cache:POdlByOdl"; + private const string redisPOdlByOdl = redisBaseAddr + ":Cache:POdlByOdl"; - private const string redisStatoCom = redisBaseAddr + "SPEC:Cache:StatoCom"; + private const string redisStatoCom = redisBaseAddr + ":Cache:StatoCom"; - private const string redisTipoArt = redisBaseAddr + "SPEC:Cache:TipoArt"; + private const string redisTipoArt = redisBaseAddr + ":Cache:TipoArt"; - private const string redisVocabolario = redisBaseAddr + "SPEC:Cache:Vocabolario"; + private const string redisVocabolario = redisBaseAddr + ":Cache:Vocabolario"; private static IConfiguration _configuration = null!; diff --git a/MP.INVE/MP.INVE.csproj b/MP.INVE/MP.INVE.csproj index 5a0477f8..33483024 100644 --- a/MP.INVE/MP.INVE.csproj +++ b/MP.INVE/MP.INVE.csproj @@ -5,7 +5,7 @@ enable enable MP.INVE - 6.16.2211.1510 + 6.16.2211.1516 diff --git a/MP.INVE/Pages/OperatoreLogin.razor b/MP.INVE/Pages/OperatoreLogin.razor index 73e37eab..20a76f37 100644 --- a/MP.INVE/Pages/OperatoreLogin.razor +++ b/MP.INVE/Pages/OperatoreLogin.razor @@ -3,23 +3,23 @@

OperatoreLogin

-
- - -
+
+ + +
- +
diff --git a/MP.INVE/Pages/OperatoreLogin.razor.cs b/MP.INVE/Pages/OperatoreLogin.razor.cs index e6b2a3a5..40220f62 100644 --- a/MP.INVE/Pages/OperatoreLogin.razor.cs +++ b/MP.INVE/Pages/OperatoreLogin.razor.cs @@ -16,6 +16,7 @@ using MP.INVE.Data; using MP.INVE.Shared; using MP.INVE.Components; using MP.Data.DatabaseModels; +using MP.Data.DTO; namespace MP.INVE.Pages { @@ -26,8 +27,11 @@ namespace MP.INVE.Pages [Inject] private NavigationManager NavManager { get; set; } = null!; - private int idOperatore { get; set; } - private string authKey { get; set; } + [Inject] + protected LoginService LServ { get; set; } = null!; + + private int idOperatore { get; set; } = 0; + private string authKey { get; set; } = ""; private List? elencoOperatori; @@ -44,12 +48,30 @@ namespace MP.INVE.Pages if (ok) { + // recupero operatore + var currOpr = elencoOperatori.Where(x => x.MatrOpr == idOperatore).FirstOrDefault(); + if (currOpr != null) + { + var oprDto = new OperatoreDTO() + { + authKey= currOpr.authKey, + CodOprExt= currOpr.CodOprExt, + Cognome= currOpr.Cognome, + isAdmin=currOpr.isAdmin, + userJWT="", + MatrOpr= currOpr.MatrOpr, + Nome= currOpr.Nome + }; + // salvo valori operatore + LServ.UserDTOSave(oprDto); + } + NavManager.NavigateTo("/Starter", true); } else { - } + } } } } \ No newline at end of file diff --git a/MP.INVE/Program.cs b/MP.INVE/Program.cs index ae34829e..ef779ba4 100644 --- a/MP.INVE/Program.cs +++ b/MP.INVE/Program.cs @@ -35,9 +35,11 @@ builder.Services.AddAuthorization(options => builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); +builder.Services.AddHttpContextAccessor(); builder.Services.AddSingleton(redisMultiplexer); builder.Services.AddSingleton(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddHttpClient(); builder.Services.AddSingleton(); diff --git a/MP.INVE/Resources/ChangeLog.html b/MP.INVE/Resources/ChangeLog.html index 875b9e27..3c5ae6f3 100644 --- a/MP.INVE/Resources/ChangeLog.html +++ b/MP.INVE/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOINVE -

Versione: 6.16.2211.1510

+

Versione: 6.16.2211.1516


Note di rilascio:
  • diff --git a/MP.INVE/Resources/VersNum.txt b/MP.INVE/Resources/VersNum.txt index bebf680a..2002665a 100644 --- a/MP.INVE/Resources/VersNum.txt +++ b/MP.INVE/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2211.1510 +6.16.2211.1516 diff --git a/MP.INVE/Resources/manifest.xml b/MP.INVE/Resources/manifest.xml index c0c8cbb8..9f89f9c7 100644 --- a/MP.INVE/Resources/manifest.xml +++ b/MP.INVE/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2211.1510 + 6.16.2211.1516 https://nexus.steamware.net/repository/SWS/MP-INVE/stable/LAST/MP.INVE.zip https://nexus.steamware.net/repository/SWS/MP-INVE/stable/LAST/ChangeLog.html false