COmpletato modifica x dati utente in cache redis

This commit is contained in:
Samuele Locatelli
2023-05-29 16:20:30 +02:00
parent 13b83369ae
commit 2ab02fabdd
9 changed files with 281 additions and 140 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>WebDoorCreator - Egalware</i>
<h4>Version: 0.9.2305.2910</h4>
<h4>Version: 0.9.2305.2916</h4>
<br /> Release note:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
0.9.2305.2910
0.9.2305.2916
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>0.9.2305.2910</version>
<version>0.9.2305.2916</version>
<url>http://nexus.steamware.net/repository/SWS/WDC/stable/WDC.UI.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/WDC/stable/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+2 -2
View File
@@ -50,8 +50,8 @@ namespace WebDoorCreator.Core
public const string rKeyRoles = $"{redisBaseAddr}:Cache:Roles";
public const string rKeyUsers = $"{redisBaseAddr}:Cache:Users";
public const string rKeyUsersAll = $"{redisBaseAddr}:Cache:UsersAll";
public const string rKeyUsersDataId = $"{redisBaseAddr}:Cache:UsersData:Id";
public const string rKeyUsersDataSearch = $"{redisBaseAddr}:Cache:UsersData:Search";
public const string rKeyUsersData = $"{redisBaseAddr}:Cache:UsersData";
public const string rKeyUsersDataSearch = $"{rKeyUsersData}:Search";
public const string rKeyUsersView = $"{redisBaseAddr}:Cache:UsersView";
public const string rKeyVocLemma = $"{redisBaseAddr}:Cache:VocLemma";
public const string rKeyLanguage = $"{redisBaseAddr}:Cache:Languages";
@@ -0,0 +1,40 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace WebDoorCreator.Data.User
{
public class ClaimConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(System.Security.Claims.Claim));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
string type = (string)jo["Type"];
string value = (string)jo["Value"];
string valueType = (string)jo["ValueType"];
string issuer = (string)jo["Issuer"];
string originalIssuer = (string)jo["OriginalIssuer"];
return new Claim(type, value, valueType, issuer, originalIssuer);
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
+1 -1
View File
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
using System.Security.Claims;
namespace WebDoorCreator.Data.User
@@ -10,7 +11,6 @@ namespace WebDoorCreator.Data.User
public class UserData
{
#region Public Properties
public List<Claim> Claims { get; set; } = new List<Claim>();
public IdentityUser Identity { get; set; } = null!;
+229 -128
View File
@@ -4,6 +4,7 @@ using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
using System.Security.Claims;
using WebDoorCreator.Core;
using WebDoorCreator.Data.User;
@@ -118,6 +119,27 @@ namespace WebDoorCreator.UI.Data
#region Public Methods
/// <summary>
/// Effettua reset dati utente...
/// </summary>
/// <param name="resetAll">Indica reset completo (anche dati elenco di base)</param>
/// <returns></returns>
public async Task<bool> ResetUserDataCache(bool resetAll)
{
bool fatto = false;
RedisValue pattern = new RedisValue($"{Constants.rKeyUsersAll}");
if (resetAll)
{
fatto = await ExecFlushRedisPattern(pattern);
}
// ora resetto il resto
pattern = new RedisValue($"{Constants.rKeyUsersData}:*");
fatto = fatto && await ExecFlushRedisPattern(pattern);
//pattern = new RedisValue($"{Constants.rKeyUsersDataSearch}:*");
//fatto = fatto && await ExecFlushRedisPattern(pattern);
return fatto;
}
/// <summary>
/// Dati utente (TUTTI) da REDIS o DB
/// </summary>
@@ -161,66 +183,37 @@ namespace WebDoorCreator.UI.Data
}
/// <summary>
/// Dati utente (singolo x UserId)
/// Dati utente (singolo x searchVal)
/// </summary>
/// <param name="UserId"></param>
/// <returns></returns>
public async Task<UserData> UserDataGetById(string UserId)
{
string source = "DB";
string source = "FULL";
UserData dataResult = new UserData();
// cerco da cache
string currKey = $"{Constants.rKeyUsersDataId}:{UserId}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = "";// await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
// uso metodi helper protected di base...
var userRaw = await UserIdentityById(UserId);
var userIdent = new IdentityUser
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<UserData>(rawData);
if (tempResult == null)
{
dataResult = new UserData();
}
else
{
dataResult = tempResult;
}
}
else
Id = userRaw.Id,
UserName = userRaw.UserName,
Email = userRaw.Email,
PhoneNumber = userRaw.PhoneNumber,
PasswordHash = "*****",
EmailConfirmed = userRaw.EmailConfirmed
};
// cerco ruoli & claims
var UserRoles = await UserRolesById(userIdent);
var UserClaims = await UserClaimsById(userIdent);
// compongo output
dataResult = new UserData()
{
// Collezione dati raw
var userRaw = await _userManager.FindByIdAsync(UserId);
if (userRaw != null)
{
var userIdent = new IdentityUser
{
Id = userRaw.Id,
UserName = userRaw.UserName,
Email = userRaw.Email,
PhoneNumber = userRaw.PhoneNumber,
PasswordHash = "*****",
EmailConfirmed = userRaw.EmailConfirmed
};
// cerco ruoli & claims
var UserRoles = await _userManager.GetRolesAsync(userIdent);
var UserClaims = await _userManager.GetClaimsAsync(userIdent);
// compongo output
dataResult = new UserData()
{
Identity = userIdent,
Roles = UserRoles.ToList(),
Claims = UserClaims.ToList()
};
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, FastCache);
}
}
if (dataResult == null)
{
dataResult = new UserData();
}
Identity = userIdent,
Roles = UserRoles,
Claims = UserClaims
};
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserDataGetById | {source} in: {ts.TotalMilliseconds} ms");
@@ -228,75 +221,41 @@ namespace WebDoorCreator.UI.Data
}
/// <summary>
/// Dati utente (filtrati da UserId)
/// Dati utente (filtrati da searchVal)
/// </summary>
/// <param name="searchVal"></param>
/// <returns></returns>
public async Task<List<UserData>> UserDataGetFilt(string searchVal)
{
string source = "DB";
string source = "FULL";
List<UserData> dataResult = new List<UserData>();
// cerco da cache
string currKey = $"{Constants.rKeyUsersDataSearch}:{searchVal}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = "";// await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
// uso metodi helper protected di base...
List<IdentityUser> RawList = await UserIdentityBySearch(searchVal);
// conversione
var user = RawList.Select(x => new IdentityUser
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<UserData>>(rawData);
if (tempResult == null)
{
dataResult = new List<UserData>();
}
else
{
dataResult = tempResult;
}
}
else
Id = x.Id,
UserName = x.UserName,
Email = x.Email,
PhoneNumber = x.PhoneNumber,
PasswordHash = "*****",
EmailConfirmed = x.EmailConfirmed
}).ToList();
foreach (var item in user)
{
// Collezione dati raw
List<IdentityUser> RawList = new List<IdentityUser>();
//List<UserData> UsersList = new List<UserData>();
var allData = await UserDataGetAll();
if (!string.IsNullOrEmpty(searchVal))
{
RawList = allData.Where(x => x.NormalizedEmail.Contains(searchVal.ToUpper()) || x.NormalizedUserName.Contains(searchVal.ToUpper())).ToList();
}
else
{
RawList = allData;
}
var user = RawList.Select(x => new IdentityUser
{
Id = x.Id,
UserName = x.UserName,
Email = x.Email,
PhoneNumber = x.PhoneNumber,
PasswordHash = "*****",
EmailConfirmed = x.EmailConfirmed
}).ToList();
// cerco ruoli & claims
var UserRoles = await UserRolesById(item);
var UserClaims = await UserClaimsById(item);
foreach (var item in user)
var newItem = new UserData()
{
var UserRoles = await _userManager.GetRolesAsync(item);
var UserClaims = await _userManager.GetClaimsAsync(item);
var newItem = new UserData()
{
Identity = item,
Roles = UserRoles.ToList(),
Claims = UserClaims.ToList()
};
dataResult.Add(newItem);
}
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, FastCache);
}
if (dataResult == null)
{
dataResult = new List<UserData>();
Identity = item,
Roles = UserRoles,
Claims = UserClaims
};
dataResult.Add(newItem);
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
@@ -304,27 +263,6 @@ namespace WebDoorCreator.UI.Data
return dataResult;
}
/// <summary>
/// Effettua reset dati utente...
/// </summary>
/// <param name="resetAll">Indica reset completo (anche dati elenco di base)</param>
/// <returns></returns>
public async Task<bool> ResetUserDataCache(bool resetAll)
{
bool fatto = false;
RedisValue pattern = new RedisValue($"{Constants.rKeyUsersAll}");
if (resetAll)
{
fatto = await ExecFlushRedisPattern(pattern);
}
// ora resetto il resto
pattern = new RedisValue($"{Constants.rKeyUsersDataId}:*");
fatto = fatto && await ExecFlushRedisPattern(pattern);
pattern = new RedisValue($"{Constants.rKeyUsersDataSearch}:*");
fatto = fatto && await ExecFlushRedisPattern(pattern);
return fatto;
}
#endregion Public Methods
#region Protected Methods
@@ -369,6 +307,169 @@ namespace WebDoorCreator.UI.Data
}
}
/// <summary>
/// Dati utente CLAIMS da REDIS o DB
/// </summary>
/// <returns></returns>
protected async Task<List<Claim>> UserClaimsById(IdentityUser UserIdent)
{
string source = "DB";
List<Claim> dataResult = new List<Claim>();
// cerco da cache
string currKey = $"{Constants.rKeyUsersData}:Claims:{UserIdent.Id}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<Claim>>(rawData, new ClaimConverter());
if (tempResult != null)
{
dataResult = tempResult;
}
}
else
{
var rawResult = await _userManager.GetClaimsAsync(UserIdent);
dataResult = rawResult.ToList();
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dataResult == null)
{
dataResult = new List<Claim>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserClaimsById | {source} in: {ts.TotalMilliseconds} ms");
return dataResult;
}
/// <summary>
/// Dati utente IDENTITY da REDIS o DB
/// </summary>
/// <returns></returns>
protected async Task<IdentityUser> UserIdentityById(string UserId)
{
string source = "DB";
IdentityUser dataResult = new IdentityUser();
// cerco da cache
string currKey = $"{Constants.rKeyUsersData}:Identity:{UserId}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<IdentityUser>(rawData);
if (tempResult != null)
{
dataResult = tempResult;
}
}
else
{
dataResult = await _userManager.FindByIdAsync(UserId);
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dataResult == null)
{
dataResult = new IdentityUser();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserIdentityById | {source} in: {ts.TotalMilliseconds} ms");
return dataResult;
}
/// <summary>
/// Dati utente IDENTITY in modalità SEARCH da REDIS o DB
/// </summary>
/// <returns></returns>
protected async Task<List<IdentityUser>> UserIdentityBySearch(string searchVal)
{
string source = "DB";
List<IdentityUser> dataResult = new List<IdentityUser>();
// cerco da cache
string currKey = $"{Constants.rKeyUsersDataSearch}:{searchVal}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<IdentityUser>>(rawData);
if (tempResult != null)
{
dataResult = tempResult;
}
}
else
{
var allData = await UserDataGetAll();
if (!string.IsNullOrEmpty(searchVal))
{
dataResult = allData
.Where(x => x.NormalizedEmail.Contains(searchVal.ToUpper()) || x.NormalizedUserName.Contains(searchVal.ToUpper())).ToList();
}
else
{
dataResult = allData;
}
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dataResult == null)
{
dataResult = new List<IdentityUser>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserIdentityBySearch | {source} in: {ts.TotalMilliseconds} ms");
return dataResult;
}
/// <summary>
/// Dati utente ROLES da REDIS o DB
/// </summary>
/// <returns></returns>
protected async Task<List<string>> UserRolesById(IdentityUser UserIdent)
{
string source = "DB";
List<string> dataResult = new List<string>();
// cerco da cache
string currKey = $"{Constants.rKeyUsersData}:Roles:{UserIdent.Id}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<string>>(rawData);
if (tempResult != null)
{
dataResult = tempResult;
}
}
else
{
var rawResult = await _userManager.GetRolesAsync(UserIdent);
dataResult = rawResult.ToList();
rawData = JsonConvert.SerializeObject(dataResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dataResult == null)
{
dataResult = new List<string>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserRolesById | {source} in: {ts.TotalMilliseconds} ms");
return dataResult;
}
#endregion Protected Methods
#region Private Fields
+5 -5
View File
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.JSInterop;
using System.Linq;
using System.Security.Claims;
using WebDoorCreator.Data.DbModels;
using WebDoorCreator.Data.Services;
using WebDoorCreator.Data.User;
@@ -57,7 +58,7 @@ namespace WebDoorCreator.UI.Pages
#region Public Methods
public List<string> ConvertClaim(List<System.Security.Claims.Claim> ClaimList)
public List<string> ConvertClaim(List<Claim> ClaimList)
{
List<string> answ = new List<string>();
@@ -164,7 +165,6 @@ namespace WebDoorCreator.UI.Pages
// filtro visualizzazione x Company, SE richeisto
if (FiltCompany != "0")
{
System.Security.Claims.Claim cClaim = new System.Security.Claims.Claim("CompanyId", $"{FiltCompany}");
UsersAll = UsersAll
.Where(x => x.Claims.Any(c => c.Type == "CompanyId" && c.Value == $"{FiltCompany}"))
.ToList();
@@ -180,7 +180,7 @@ namespace WebDoorCreator.UI.Pages
StateHasChanged();
}
public string ShowClaims(List<System.Security.Claims.Claim> ClaimList)
public string ShowClaims(List<Claim> ClaimList)
{
string answ = string.Join(",", ConvertClaim(ClaimList));
return answ;
@@ -321,9 +321,9 @@ namespace WebDoorCreator.UI.Pages
[Inject]
private IConfiguration Configuration { get; set; } = null!;
private System.Security.Claims.Claim CurrentUserClaim
private Claim CurrentUserClaim
{
get => new System.Security.Claims.Claim(CurrentUserClaimType, CurrentUserClaimVal);
get => new Claim(CurrentUserClaimType, CurrentUserClaimVal);
}
/// <summary>
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Version>0.9.2305.2910</Version>
<Version>0.9.2305.2916</Version>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aspnet-WebDoorCreator.UI-dfe95fed-1398-4144-bd43-8b3a765d6608</UserSecretsId>
</PropertyGroup>