Refactor: Web Consolidation and Identity Stabilization #40
@@ -17,6 +17,8 @@ public record UserProfileDto
|
||||
/// Summary of the last read book.
|
||||
/// </summary>
|
||||
public LastReadBookDto? LastReadBook { get; init; }
|
||||
|
||||
public string[] Roles { get; init; } = Array.Empty<string>();
|
||||
}
|
||||
|
||||
public record LastReadBookDto
|
||||
|
||||
@@ -48,7 +48,11 @@ public class GetUserProfileQueryHandler : IRequestHandler<GetUserProfileQuery, R
|
||||
Progress = e.Progress,
|
||||
LastChapter = e.LastChapter ?? "Rozpoczynanie...",
|
||||
LastChapterIndex = e.LastChapterIndex
|
||||
}).FirstOrDefault()
|
||||
}).FirstOrDefault(),
|
||||
Roles = dbContext.UserRoles
|
||||
.Where(ur => ur.UserId == u.Id)
|
||||
.Join(dbContext.Roles, ur => ur.RoleId, r => r.Id, (ur, r) => r.Name!)
|
||||
.ToArray()
|
||||
})
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
|
||||
@@ -6,4 +6,5 @@ public static class StorageKeys
|
||||
public const string RefreshToken = "nexus_refresh_token";
|
||||
public const string UserEmail = "nexus_user_email";
|
||||
public const string UserTenant = "nexus_user_tenant";
|
||||
public const string UserRoles = "nexus_user_roles";
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ public record UserProfile(
|
||||
Guid TenantId,
|
||||
SubscriptionPlanDto Plan,
|
||||
int AverageQuizScore,
|
||||
LastReadBookDto? LastReadBook)
|
||||
LastReadBookDto? LastReadBook,
|
||||
string[] Roles)
|
||||
{
|
||||
// Helper properties for UI compatibility
|
||||
public string CurrentPlan => Plan?.Name ?? PlanConstants.DefaultPlanName;
|
||||
@@ -104,11 +105,15 @@ public class IdentityService : IIdentityService
|
||||
var profile = profileResult.Value;
|
||||
await _storageService.SaveSecureString(StorageKeys.UserEmail, profile.Email);
|
||||
await _storageService.SaveSecureString(StorageKeys.UserTenant, profile.TenantId.ToString());
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString());
|
||||
|
||||
var rolesStr = string.Join(",", profile.Roles ?? Array.Empty<string>());
|
||||
await _storageService.SaveSecureString(StorageKeys.UserRoles, rolesStr);
|
||||
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString(), rolesStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(email, "unknown");
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(email, "unknown", "");
|
||||
}
|
||||
|
||||
return Result.Ok();
|
||||
@@ -132,6 +137,7 @@ public class IdentityService : IIdentityService
|
||||
await _storageService.SaveSecureString(RefreshTokenKey, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserEmail, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserTenant, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserRoles, "");
|
||||
}
|
||||
|
||||
if (OnStateInvalidated != null) await OnStateInvalidated.Invoke();
|
||||
@@ -197,7 +203,11 @@ public class IdentityService : IIdentityService
|
||||
_cachedProfile = profile;
|
||||
await _storageService.SaveSecureString(StorageKeys.UserEmail, profile.Email);
|
||||
await _storageService.SaveSecureString(StorageKeys.UserTenant, profile.TenantId.ToString());
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString());
|
||||
|
||||
var rolesStr = string.Join(",", profile.Roles ?? Array.Empty<string>());
|
||||
await _storageService.SaveSecureString(StorageKeys.UserRoles, rolesStr);
|
||||
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString(), rolesStr);
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
@@ -246,7 +256,11 @@ public class IdentityService : IIdentityService
|
||||
var profile = profileResult.Value;
|
||||
await _storageService.SaveSecureString(StorageKeys.UserEmail, profile.Email);
|
||||
await _storageService.SaveSecureString(StorageKeys.UserTenant, profile.TenantId.ToString());
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString());
|
||||
|
||||
var rolesStr = string.Join(",", profile.Roles ?? Array.Empty<string>());
|
||||
await _storageService.SaveSecureString(StorageKeys.UserRoles, rolesStr);
|
||||
|
||||
(_authStateProvider as NexusAuthenticationStateProvider)?.NotifyUserAuthentication(profile.Email, profile.TenantId.ToString(), rolesStr);
|
||||
}
|
||||
|
||||
return Result.Ok();
|
||||
|
||||
@@ -38,10 +38,15 @@ public class NexusAuthenticationStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
var emailResult = await _storageService.GetSecureString(StorageKeys.UserEmail);
|
||||
var tenantIdResult = await _storageService.GetSecureString(StorageKeys.UserTenant);
|
||||
var rolesResult = await _storageService.GetSecureString(StorageKeys.UserRoles);
|
||||
|
||||
if (emailResult.IsSuccess && !string.IsNullOrEmpty(emailResult.Value))
|
||||
{
|
||||
_cachedState = CreateState(emailResult.Value, tenantIdResult.IsSuccess ? tenantIdResult.Value! : "unknown", "OpaqueBearer");
|
||||
_cachedState = CreateState(
|
||||
emailResult.Value,
|
||||
tenantIdResult.IsSuccess ? tenantIdResult.Value! : "unknown",
|
||||
"OpaqueBearer",
|
||||
rolesResult.IsSuccess ? rolesResult.Value! : "");
|
||||
return _cachedState;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +56,12 @@ public class NexusAuthenticationStateProvider : AuthenticationStateProvider
|
||||
if (storedEmailResult.IsSuccess && !string.IsNullOrEmpty(storedEmailResult.Value))
|
||||
{
|
||||
var tenantIdResult = await _storageService.GetSecureString(StorageKeys.UserTenant);
|
||||
_cachedState = CreateState(storedEmailResult.Value, tenantIdResult.IsSuccess ? tenantIdResult.Value! : "unknown", "CookieAuth");
|
||||
var rolesResult = await _storageService.GetSecureString(StorageKeys.UserRoles);
|
||||
_cachedState = CreateState(
|
||||
storedEmailResult.Value,
|
||||
tenantIdResult.IsSuccess ? tenantIdResult.Value! : "unknown",
|
||||
"CookieAuth",
|
||||
rolesResult.IsSuccess ? rolesResult.Value! : "");
|
||||
return _cachedState;
|
||||
}
|
||||
|
||||
@@ -67,7 +77,7 @@ public class NexusAuthenticationStateProvider : AuthenticationStateProvider
|
||||
}
|
||||
}
|
||||
|
||||
private AuthenticationState CreateState(string email, string tenantId, string authType)
|
||||
private AuthenticationState CreateState(string email, string tenantId, string authType, string rolesStr = "")
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
@@ -75,13 +85,23 @@ public class NexusAuthenticationStateProvider : AuthenticationStateProvider
|
||||
new Claim(ClaimTypes.Email, email),
|
||||
new Claim("TenantId", tenantId)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(rolesStr))
|
||||
{
|
||||
var roles = rolesStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var role in roles)
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, role.Trim()));
|
||||
}
|
||||
}
|
||||
|
||||
var identity = new ClaimsIdentity(claims, authType);
|
||||
return new AuthenticationState(new ClaimsPrincipal(identity));
|
||||
}
|
||||
|
||||
public void NotifyUserAuthentication(string email, string tenantId)
|
||||
public void NotifyUserAuthentication(string email, string tenantId, string rolesStr = "")
|
||||
{
|
||||
_cachedState = CreateState(email, tenantId, "OpaqueBearer");
|
||||
_cachedState = CreateState(email, tenantId, "OpaqueBearer", rolesStr);
|
||||
NotifyAuthenticationStateChanged(Task.FromResult(_cachedState));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ public class ServerIdentityService : IIdentityService
|
||||
await _storageService.SaveSecureString(StorageKeys.RefreshToken, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserEmail, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserTenant, "");
|
||||
await _storageService.SaveSecureString(StorageKeys.UserRoles, "");
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -88,7 +89,8 @@ public class ServerIdentityService : IIdentityService
|
||||
dto.TenantId,
|
||||
dto.Plan,
|
||||
dto.AverageQuizScore,
|
||||
dto.LastReadBook
|
||||
dto.LastReadBook,
|
||||
dto.Roles
|
||||
);
|
||||
|
||||
return Result.Ok(profile);
|
||||
|
||||
Reference in New Issue
Block a user