-
Notifications
You must be signed in to change notification settings - Fork 306
Expand file tree
/
Copy pathUserProfileStateService.cs
More file actions
109 lines (93 loc) · 3.47 KB
/
UserProfileStateService.cs
File metadata and controls
109 lines (93 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using AutoMapper.QueryableExtensions;
using CleanArchitecture.Blazor.Application.Features.Identity.DTOs;
using CleanArchitecture.Blazor.Domain.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using ZiggyCreatures.Caching.Fusion;
namespace CleanArchitecture.Blazor.Application.Common.Security;
public class UserProfileStateService : IDisposable
{
// Cache refresh interval of 60 seconds
private TimeSpan RefreshInterval => TimeSpan.FromSeconds(60);
// Internal user profile state
private UserProfile _userProfile = new UserProfile { Email = "", UserId = "", UserName = "" };
// Dependencies
private readonly UserManager<ApplicationUser> _userManager;
private readonly IMapper _mapper;
private readonly IFusionCache _fusionCache;
private readonly IServiceScope _scope;
public UserProfileStateService(
IMapper mapper,
IServiceScopeFactory scopeFactory,
IFusionCache fusionCache)
{
_scope = scopeFactory.CreateScope();
_userManager = _scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
_mapper = mapper;
_fusionCache = fusionCache;
}
/// <summary>
/// Loads and initializes the user profile from the database.
/// </summary>
public async Task InitializeAsync(string userName)
{
var key = GetApplicationUserCacheKey(userName);
var result = await _fusionCache.GetOrSetAsync(
key,
_ => _userManager.Users
.Where(x => x.UserName == userName)
.Include(x => x.UserRoles).ThenInclude(x => x.Role)
.ProjectTo<ApplicationUserDto>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync(),
RefreshInterval);
if (result is not null)
{
_userProfile = result.ToUserProfile();
NotifyStateChanged();
}
}
/// <summary>
/// Gets or sets the current user profile.
/// </summary>
public UserProfile UserProfile
{
get => _userProfile;
set
{
_userProfile = value;
NotifyStateChanged();
}
}
/// <summary>
/// Refreshes the user profile by removing the cached value and reloading data from the database.
/// </summary>
public async Task RefreshAsync(string userName)
{
RemoveApplicationUserCache(userName);
await InitializeAsync(userName);
}
/// <summary>
/// Updates the user profile and clears the cache.
/// </summary>
public void UpdateUserProfile(string userName, string? profilePictureDataUrl, string? fullName, string? phoneNumber, string? timeZoneId, string? languageCode)
{
_userProfile.ProfilePictureDataUrl = profilePictureDataUrl;
_userProfile.DisplayName = fullName;
_userProfile.PhoneNumber = phoneNumber;
_userProfile.TimeZoneId = timeZoneId;
_userProfile.LanguageCode = languageCode;
RemoveApplicationUserCache(userName);
NotifyStateChanged();
}
public event Func<Task>? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
private string GetApplicationUserCacheKey(string userName)
{
return $"GetApplicationUserDto:{userName}";
}
public void RemoveApplicationUserCache(string userName)
{
_fusionCache.Remove(GetApplicationUserCacheKey(userName));
}
public void Dispose() => _scope.Dispose();
}