fix #4284 - handle user role effective and expiry date
This commit is contained in:
parent
8b2e55a969
commit
8ca2f0a49f
|
@ -11,7 +11,7 @@
|
||||||
<div class="search-result-container">
|
<div class="search-result-container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<form method="post" @formname="SearchInputForm" @onsubmit="Search" data-enhance>
|
<form method="post" @formname="SearchResultsForm" @onsubmit="Search" data-enhance>
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text">@Localizer["SearchLabel"]</span>
|
<span class="input-group-text">@Localizer["SearchLabel"]</span>
|
||||||
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
|
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
private SearchResults _searchResults;
|
private SearchResults _searchResults;
|
||||||
private bool _loading;
|
private bool _loading;
|
||||||
|
|
||||||
[SupplyParameterFromForm(FormName = "SearchInputForm")]
|
[SupplyParameterFromForm(FormName = "SearchResultsForm")]
|
||||||
public string KeyWords { get => ""; set => _keywords = value; }
|
public string KeyWords { get => ""; set => _keywords = value; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Oqtane.Services
|
||||||
|
|
||||||
public async Task<User> GetUserAsync(string username, int siteId)
|
public async Task<User> GetUserAsync(string username, int siteId)
|
||||||
{
|
{
|
||||||
return await GetUserAsync(username, "", siteId);
|
return await GetJsonAsync<User>($"{Apiurl}/username/{username}?siteid={siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<User> GetUserAsync(string username, string email, int siteId)
|
public async Task<User> GetUserAsync(string username, string email, int siteId)
|
||||||
|
|
|
@ -4,16 +4,15 @@
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@inject IStringLocalizer<Search> Localizer
|
@inject IStringLocalizer<Search> Localizer
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IHttpContextAccessor HttpContext
|
|
||||||
|
|
||||||
@if (_searchResultsPage != null)
|
@if (_searchResultsPage != null)
|
||||||
{
|
{
|
||||||
<span class="app-search @CssClass">
|
<span class="app-search @CssClass">
|
||||||
<form method="post" class="app-form-inline" @formname="@($"{Position}SearchForm")" @onsubmit="@PerformSearch" data-enhance>
|
<form method="post" class="app-form-inline" @formname="@($"SearchForm")" @onsubmit="@PerformSearch" data-enhance>
|
||||||
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
|
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
|
||||||
<input type="text" name="keywords" maxlength="50"
|
<input type="text" name="keywords" maxlength="50"
|
||||||
class="form-control d-inline-block pe-5 shadow-none"
|
class="form-control d-inline-block pe-5 shadow-none"
|
||||||
@bind-value="_keywords"
|
@bind="_keywords"
|
||||||
placeholder="@Localizer["SearchPlaceHolder"]"
|
placeholder="@Localizer["SearchPlaceHolder"]"
|
||||||
aria-label="Search" />
|
aria-label="Search" />
|
||||||
<button type="submit" class="btn btn-search">
|
<button type="submit" class="btn btn-search">
|
||||||
|
@ -32,12 +31,15 @@
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string CssClass { get; set; }
|
public string CssClass { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string Position { get; set; } = "Main";
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string SearchResultPagePath { get; set; } = "search";
|
public string SearchResultPagePath { get; set; } = "search";
|
||||||
|
|
||||||
|
[CascadingParameter]
|
||||||
|
HttpContext HttpContext { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromForm(FormName = "SearchForm")]
|
||||||
|
public string KeyWords { get => ""; set => _keywords = value; }
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrEmpty(SearchResultPagePath))
|
if(!string.IsNullOrEmpty(SearchResultPagePath))
|
||||||
|
@ -46,16 +48,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PerformSearch()
|
private void PerformSearch()
|
||||||
{
|
{
|
||||||
var keywords = HttpContext.HttpContext.Request.Form["keywords"];
|
|
||||||
if (_searchResultsPage != null)
|
if (_searchResultsPage != null)
|
||||||
{
|
{
|
||||||
var url = NavigateUrl(_searchResultsPage.Path, $"q={keywords}");
|
var url = NavigateUrl(_searchResultsPage.Path, $"q={_keywords}");
|
||||||
NavigationManager.NavigateTo(url);
|
NavigationManager.NavigateTo(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
}
|
}
|
||||||
_comment += " -->";
|
_comment += " -->";
|
||||||
|
|
||||||
if (PageState.RenderMode != RenderModes.Static || ModuleState.RenderMode != RenderModes.Static)
|
if (PageState.RenderMode == RenderModes.Static && ModuleState.RenderMode == RenderModes.Interactive)
|
||||||
{
|
{
|
||||||
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
|
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
|
||||||
// please note that this performance optimization results in the PageState.Pages property not being available for use in Interactive components
|
// please note that this performance optimization results in the PageState.Pages property not being available for use in Interactive components
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
@using System.Net
|
@using System.Net
|
||||||
@using Microsoft.AspNetCore.Http
|
@using Microsoft.AspNetCore.Http
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
|
@using System.Security.Claims
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||||
@inject SiteState SiteState
|
@inject SiteState SiteState
|
||||||
|
@ -159,7 +160,8 @@
|
||||||
if (authState.User.Identity.IsAuthenticated && authState.User.Claims.Any(item => item.Type == "sitekey" && item.Value == SiteState.Alias.SiteKey))
|
if (authState.User.Identity.IsAuthenticated && authState.User.Claims.Any(item => item.Type == "sitekey" && item.Value == SiteState.Alias.SiteKey))
|
||||||
{
|
{
|
||||||
// get user
|
// get user
|
||||||
user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId);
|
var userid = int.Parse(authState.User.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
|
||||||
|
user = await UserService.GetUserAsync(userid, SiteState.Alias.SiteId);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
||||||
|
|
|
@ -72,15 +72,13 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/name/{name}/{email}?siteid=x
|
// GET api/<controller>/username/{username}?siteid=x
|
||||||
[HttpGet("name/{name}/{email}")]
|
[HttpGet("username/{username}")]
|
||||||
public User Get(string name, string email, string siteid)
|
public User Get(string username, string siteid)
|
||||||
{
|
{
|
||||||
if (int.TryParse(siteid, out int SiteId) && SiteId == _tenantManager.GetAlias().SiteId)
|
if (int.TryParse(siteid, out int SiteId) && SiteId == _tenantManager.GetAlias().SiteId)
|
||||||
{
|
{
|
||||||
name = (name == "-") ? "" : name;
|
User user = _userManager.GetUser(username, SiteId);
|
||||||
email = (email == "-") ? "" : email;
|
|
||||||
User user = _userManager.GetUser(name, email, SiteId);
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
@ -95,7 +93,36 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Get Attempt {Username} {Email} {SiteId}", name, email, siteid);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Get Attempt {Username} {SiteId}", username, siteid);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/name/{username}/{email}?siteid=x
|
||||||
|
[HttpGet("search/{username}/{email}")]
|
||||||
|
public User Get(string username, string email, string siteid)
|
||||||
|
{
|
||||||
|
if (int.TryParse(siteid, out int SiteId) && SiteId == _tenantManager.GetAlias().SiteId)
|
||||||
|
{
|
||||||
|
username = (username == "-") ? "" : username;
|
||||||
|
email = (email == "-") ? "" : email;
|
||||||
|
User user = _userManager.GetUser(username, email, SiteId);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Setting> settings = _settings.GetSettings(EntityNames.User, user.UserId).ToList();
|
||||||
|
user.Settings = settings.Where(item => !item.IsPrivate || _userPermissions.GetUser(User).UserId == user.UserId)
|
||||||
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
||||||
|
}
|
||||||
|
return Filter(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Get Attempt {Username} {Email} {SiteId}", username, email, siteid);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -340,14 +367,11 @@ namespace Oqtane.Controllers
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
user.Username = User.Identity.Name;
|
user.Username = User.Identity.Name;
|
||||||
if (User.HasClaim(item => item.Type == ClaimTypes.NameIdentifier))
|
user.UserId = User.UserId();
|
||||||
{
|
|
||||||
user.UserId = int.Parse(User.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
|
|
||||||
}
|
|
||||||
string roles = "";
|
string roles = "";
|
||||||
foreach (var claim in User.Claims.Where(item => item.Type == ClaimTypes.Role))
|
foreach (var roleName in User.Roles())
|
||||||
{
|
{
|
||||||
roles += claim.Value + ";";
|
roles += roleName + ";";
|
||||||
}
|
}
|
||||||
if (roles != "") roles = ";" + roles;
|
if (roles != "") roles = ";" + roles;
|
||||||
user.Roles = roles;
|
user.Roles = roles;
|
||||||
|
|
|
@ -33,14 +33,10 @@ namespace Oqtane.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Roles(this ClaimsPrincipal claimsPrincipal)
|
public static string[] Roles(this ClaimsPrincipal claimsPrincipal)
|
||||||
{
|
{
|
||||||
var roles = "";
|
return claimsPrincipal.Claims.Where(item => item.Type == ClaimTypes.Role)
|
||||||
foreach (var claim in claimsPrincipal.Claims.Where(item => item.Type == ClaimTypes.Role))
|
.Select(item => item.Value).ToArray();
|
||||||
{
|
|
||||||
roles += ((roles == "") ? "" : ";") + claim.Value;
|
|
||||||
}
|
|
||||||
return roles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string SiteKey(this ClaimsPrincipal claimsPrincipal)
|
public static string SiteKey(this ClaimsPrincipal claimsPrincipal)
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
|
@ -25,15 +26,15 @@ namespace Oqtane.Managers
|
||||||
private readonly ITenantManager _tenantManager;
|
private readonly ITenantManager _tenantManager;
|
||||||
private readonly INotificationRepository _notifications;
|
private readonly INotificationRepository _notifications;
|
||||||
private readonly IFolderRepository _folders;
|
private readonly IFolderRepository _folders;
|
||||||
private readonly IFileRepository _files;
|
|
||||||
private readonly IProfileRepository _profiles;
|
private readonly IProfileRepository _profiles;
|
||||||
private readonly ISettingRepository _settings;
|
private readonly ISettingRepository _settings;
|
||||||
|
private readonly ISiteRepository _sites;
|
||||||
private readonly ISyncManager _syncManager;
|
private readonly ISyncManager _syncManager;
|
||||||
private readonly ILogManager _logger;
|
private readonly ILogManager _logger;
|
||||||
|
private readonly IMemoryCache _cache;
|
||||||
private readonly IStringLocalizer<UserManager> _localizer;
|
private readonly IStringLocalizer<UserManager> _localizer;
|
||||||
private readonly ISiteRepository _siteRepo;
|
|
||||||
|
|
||||||
public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IFileRepository files, IProfileRepository profiles, ISettingRepository settings, ISyncManager syncManager, ILogManager logger, IStringLocalizer<UserManager> localizer, ISiteRepository siteRepo)
|
public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IProfileRepository profiles, ISettingRepository settings, ISiteRepository sites, ISyncManager syncManager, ILogManager logger, IMemoryCache cache, IStringLocalizer<UserManager> localizer)
|
||||||
{
|
{
|
||||||
_users = users;
|
_users = users;
|
||||||
_roles = roles;
|
_roles = roles;
|
||||||
|
@ -43,18 +44,34 @@ namespace Oqtane.Managers
|
||||||
_tenantManager = tenantManager;
|
_tenantManager = tenantManager;
|
||||||
_notifications = notifications;
|
_notifications = notifications;
|
||||||
_folders = folders;
|
_folders = folders;
|
||||||
_files = files;
|
|
||||||
_profiles = profiles;
|
_profiles = profiles;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
_sites = sites;
|
||||||
_syncManager = syncManager;
|
_syncManager = syncManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_cache = cache;
|
||||||
_localizer = localizer;
|
_localizer = localizer;
|
||||||
_siteRepo = siteRepo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User GetUser(int userid, int siteid)
|
public User GetUser(int userid, int siteid)
|
||||||
{
|
{
|
||||||
User user = _users.GetUser(userid);
|
var alias = _tenantManager.GetAlias();
|
||||||
|
return _cache.GetOrCreate($"user:{userid}:{alias.SiteKey}", entry =>
|
||||||
|
{
|
||||||
|
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
|
||||||
|
User user = _users.GetUser(userid);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
user.SiteId = siteid;
|
||||||
|
user.Roles = GetUserRoles(user.UserId, user.SiteId);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public User GetUser(string username, int siteid)
|
||||||
|
{
|
||||||
|
User user = _users.GetUser(username);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
user.SiteId = siteid;
|
user.SiteId = siteid;
|
||||||
|
@ -63,11 +80,6 @@ namespace Oqtane.Managers
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User GetUser(string username, int siteid)
|
|
||||||
{
|
|
||||||
return GetUser(username, "", siteid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public User GetUser(string username, string email, int siteid)
|
public User GetUser(string username, string email, int siteid)
|
||||||
{
|
{
|
||||||
User user = _users.GetUser(username, email);
|
User user = _users.GetUser(username, email);
|
||||||
|
@ -85,14 +97,17 @@ namespace Oqtane.Managers
|
||||||
List<UserRole> userroles = _userRoles.GetUserRoles(userId, siteId).ToList();
|
List<UserRole> userroles = _userRoles.GetUserRoles(userId, siteId).ToList();
|
||||||
foreach (UserRole userrole in userroles)
|
foreach (UserRole userrole in userroles)
|
||||||
{
|
{
|
||||||
roles += userrole.Role.Name + ";";
|
if (Utilities.IsEffectiveOrExpired(userrole.EffectiveDate, userrole.ExpiryDate))
|
||||||
if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Admin))
|
|
||||||
{
|
{
|
||||||
roles += RoleNames.Admin + ";";
|
roles += userrole.Role.Name + ";";
|
||||||
}
|
if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Admin))
|
||||||
if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Registered))
|
{
|
||||||
{
|
roles += RoleNames.Admin + ";";
|
||||||
roles += RoleNames.Registered + ";";
|
}
|
||||||
|
if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Registered))
|
||||||
|
{
|
||||||
|
roles += RoleNames.Registered + ";";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (roles != "") roles = ";" + roles;
|
if (roles != "") roles = ";" + roles;
|
||||||
|
@ -153,7 +168,7 @@ namespace Oqtane.Managers
|
||||||
|
|
||||||
if (User != null)
|
if (User != null)
|
||||||
{
|
{
|
||||||
string siteName = _siteRepo.GetSite(user.SiteId).Name;
|
string siteName = _sites.GetSite(user.SiteId).Name;
|
||||||
if (!user.EmailConfirmed)
|
if (!user.EmailConfirmed)
|
||||||
{
|
{
|
||||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
|
@ -201,6 +216,8 @@ namespace Oqtane.Managers
|
||||||
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||||
if (identityuser != null)
|
if (identityuser != null)
|
||||||
{
|
{
|
||||||
|
var alias = _tenantManager.GetAlias();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(user.Password))
|
if (!string.IsNullOrEmpty(user.Password))
|
||||||
{
|
{
|
||||||
var validator = new PasswordValidator<IdentityUser>();
|
var validator = new PasswordValidator<IdentityUser>();
|
||||||
|
@ -224,7 +241,6 @@ namespace Oqtane.Managers
|
||||||
// if email address changed and it is not confirmed, verification is required for new email address
|
// if email address changed and it is not confirmed, verification is required for new email address
|
||||||
if (!user.EmailConfirmed)
|
if (!user.EmailConfirmed)
|
||||||
{
|
{
|
||||||
var alias = _tenantManager.GetAlias();
|
|
||||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
string body = "Dear " + user.DisplayName + ",\n\nIn Order To Verify The Email Address Associated To Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
string body = "Dear " + user.DisplayName + ",\n\nIn Order To Verify The Email Address Associated To Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
||||||
|
@ -242,6 +258,7 @@ namespace Oqtane.Managers
|
||||||
user = _users.UpdateUser(user);
|
user = _users.UpdateUser(user);
|
||||||
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update);
|
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update);
|
||||||
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Reload);
|
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Reload);
|
||||||
|
_cache.Remove($"user:{user.UserId}:{alias.SiteKey}");
|
||||||
user.Password = ""; // remove sensitive information
|
user.Password = ""; // remove sensitive information
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "User Updated {User}", user);
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "User Updated {User}", user);
|
||||||
}
|
}
|
||||||
|
@ -324,7 +341,7 @@ namespace Oqtane.Managers
|
||||||
_users.UpdateUser(user);
|
_users.UpdateUser(user);
|
||||||
var alias = _tenantManager.GetAlias();
|
var alias = _tenantManager.GetAlias();
|
||||||
string url = alias.Protocol + alias.Name;
|
string url = alias.Protocol + alias.Name;
|
||||||
string siteName = _siteRepo.GetSite(alias.SiteId).Name;
|
string siteName = _sites.GetSite(alias.SiteId).Name;
|
||||||
string subject = _localizer["TwoFactorEmailSubject"];
|
string subject = _localizer["TwoFactorEmailSubject"];
|
||||||
subject = subject.Replace("[SiteName]", siteName);
|
subject = subject.Replace("[SiteName]", siteName);
|
||||||
string body = _localizer["TwoFactorEmailBody"].Value;
|
string body = _localizer["TwoFactorEmailBody"].Value;
|
||||||
|
@ -376,7 +393,7 @@ namespace Oqtane.Managers
|
||||||
user = _users.GetUser(user.Username);
|
user = _users.GetUser(user.Username);
|
||||||
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
|
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
|
||||||
string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
string siteName = _siteRepo.GetSite(alias.SiteId).Name;
|
string siteName = _sites.GetSite(alias.SiteId).Name;
|
||||||
string subject = _localizer["UserLockoutEmailSubject"];
|
string subject = _localizer["UserLockoutEmailSubject"];
|
||||||
subject = subject.Replace("[SiteName]", siteName);
|
subject = subject.Replace("[SiteName]", siteName);
|
||||||
string body = _localizer["UserLockoutEmailBody"].Value;
|
string body = _localizer["UserLockoutEmailBody"].Value;
|
||||||
|
@ -429,7 +446,7 @@ namespace Oqtane.Managers
|
||||||
user = _users.GetUser(user.Username);
|
user = _users.GetUser(user.Username);
|
||||||
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
|
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
|
||||||
string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
string siteName = _siteRepo.GetSite(alias.SiteId).Name;
|
string siteName = _sites.GetSite(alias.SiteId).Name;
|
||||||
string subject = _localizer["ForgotPasswordEmailSubject"];
|
string subject = _localizer["ForgotPasswordEmailSubject"];
|
||||||
subject = subject.Replace("[SiteName]", siteName);
|
subject = subject.Replace("[SiteName]", siteName);
|
||||||
string body = _localizer["ForgotPasswordEmailBody"].Value;
|
string body = _localizer["ForgotPasswordEmailBody"].Value;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
@ -10,11 +13,15 @@ namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
private readonly IDbContextFactory<TenantDBContext> _dbContextFactory;
|
private readonly IDbContextFactory<TenantDBContext> _dbContextFactory;
|
||||||
private readonly IRoleRepository _roles;
|
private readonly IRoleRepository _roles;
|
||||||
|
private readonly ITenantManager _tenantManager;
|
||||||
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
public UserRoleRepository(IDbContextFactory<TenantDBContext> dbContextFactory, IRoleRepository roles)
|
public UserRoleRepository(IDbContextFactory<TenantDBContext> dbContextFactory, IRoleRepository roles, ITenantManager tenantManager, IMemoryCache cache)
|
||||||
{
|
{
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContextFactory = dbContextFactory;
|
||||||
_roles = roles;
|
_roles = roles;
|
||||||
|
_tenantManager = tenantManager;
|
||||||
|
_cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<UserRole> GetUserRoles(int siteId)
|
public IEnumerable<UserRole> GetUserRoles(int siteId)
|
||||||
|
@ -28,11 +35,16 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public IEnumerable<UserRole> GetUserRoles(int userId, int siteId)
|
public IEnumerable<UserRole> GetUserRoles(int userId, int siteId)
|
||||||
{
|
{
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
var alias = _tenantManager.GetAlias();
|
||||||
return db.UserRole
|
return _cache.GetOrCreate($"userroles:{userId}:{alias.SiteKey}", entry =>
|
||||||
.Include(item => item.Role) // eager load roles
|
{
|
||||||
.Include(item => item.User) // eager load users
|
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
|
||||||
.Where(item => (item.Role.SiteId == siteId || item.Role.SiteId == null || siteId == -1) && item.UserId == userId).ToList();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
|
return db.UserRole
|
||||||
|
.Include(item => item.Role) // eager load roles
|
||||||
|
.Include(item => item.User) // eager load users
|
||||||
|
.Where(item => (item.Role.SiteId == siteId || item.Role.SiteId == null || siteId == -1) && item.UserId == userId).ToList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<UserRole> GetUserRoles(string roleName, int siteId)
|
public IEnumerable<UserRole> GetUserRoles(string roleName, int siteId)
|
||||||
|
@ -57,6 +69,10 @@ namespace Oqtane.Repository
|
||||||
DeleteUserRoles(userRole.UserId);
|
DeleteUserRoles(userRole.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var alias = _tenantManager.GetAlias();
|
||||||
|
_cache.Remove($"user:{userRole.UserId}:{alias.SiteKey}");
|
||||||
|
_cache.Remove($"userroles:{userRole.UserId}:{alias.SiteKey}");
|
||||||
|
|
||||||
return userRole;
|
return userRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +81,11 @@ namespace Oqtane.Repository
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
db.Entry(userRole).State = EntityState.Modified;
|
db.Entry(userRole).State = EntityState.Modified;
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
|
var alias = _tenantManager.GetAlias();
|
||||||
|
_cache.Remove($"user:{userRole.UserId}:{alias.SiteKey}");
|
||||||
|
_cache.Remove($"userroles:{userRole.UserId}:{alias.SiteKey}");
|
||||||
|
|
||||||
return userRole;
|
return userRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +143,10 @@ namespace Oqtane.Repository
|
||||||
var userRole = db.UserRole.Find(userRoleId);
|
var userRole = db.UserRole.Find(userRoleId);
|
||||||
db.UserRole.Remove(userRole);
|
db.UserRole.Remove(userRole);
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
|
var alias = _tenantManager.GetAlias();
|
||||||
|
_cache.Remove($"user:{userRole.UserId}:{alias.SiteKey}");
|
||||||
|
_cache.Remove($"userroles:{userRole.UserId}:{alias.SiteKey}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteUserRoles(int userId)
|
public void DeleteUserRoles(int userId)
|
||||||
|
@ -132,6 +157,10 @@ namespace Oqtane.Repository
|
||||||
db.UserRole.Remove(userRole);
|
db.UserRole.Remove(userRole);
|
||||||
}
|
}
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
|
var alias = _tenantManager.GetAlias();
|
||||||
|
_cache.Remove($"user:{userId}:{alias.SiteKey}");
|
||||||
|
_cache.Remove($"userroles:{userId}:{alias.SiteKey}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Oqtane.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Security
|
namespace Oqtane.Security
|
||||||
{
|
{
|
||||||
|
@ -26,11 +27,13 @@ namespace Oqtane.Security
|
||||||
public class UserPermissions : IUserPermissions
|
public class UserPermissions : IUserPermissions
|
||||||
{
|
{
|
||||||
private readonly IPermissionRepository _permissions;
|
private readonly IPermissionRepository _permissions;
|
||||||
|
private readonly IUserRoleRepository _userRoles;
|
||||||
private readonly IHttpContextAccessor _accessor;
|
private readonly IHttpContextAccessor _accessor;
|
||||||
|
|
||||||
public UserPermissions(IPermissionRepository permissions, IHttpContextAccessor accessor)
|
public UserPermissions(IPermissionRepository permissions, IUserRoleRepository userRoles, IHttpContextAccessor accessor)
|
||||||
{
|
{
|
||||||
_permissions = permissions;
|
_permissions = permissions;
|
||||||
|
_userRoles = userRoles;
|
||||||
_accessor = accessor;
|
_accessor = accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +74,24 @@ namespace Oqtane.Security
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
user.Username = principal.Identity.Name;
|
user.Username = principal.Identity.Name;
|
||||||
if (principal.Claims.Any(item => item.Type == ClaimTypes.NameIdentifier))
|
user.UserId = principal.UserId();
|
||||||
|
|
||||||
|
// include roles
|
||||||
|
var userRoles = _userRoles.GetUserRoles(user.UserId, principal.SiteId()).ToList();
|
||||||
|
foreach (var roleName in principal.Roles())
|
||||||
{
|
{
|
||||||
user.UserId = int.Parse(principal.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
|
var role = userRoles.FirstOrDefault(item => item.Role.Name == roleName);
|
||||||
}
|
if (role != null)
|
||||||
foreach (var claim in principal.Claims.Where(item => item.Type == ClaimTypes.Role))
|
{
|
||||||
{
|
if (Utilities.IsEffectiveOrExpired(role.EffectiveDate,role.ExpiryDate))
|
||||||
user.Roles += claim.Value + ";";
|
{
|
||||||
|
user.Roles += roleName + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user.Roles += roleName + ";";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (user.Roles != "") user.Roles = ";" + user.Roles;
|
if (user.Roles != "") user.Roles = ";" + user.Roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Oqtane.Models
|
||||||
public DateTime? LastLoginOn { get; set; }
|
public DateTime? LastLoginOn { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tracking information of IP used when the user last worked on this site.
|
/// IP address when the user last logged in to this site.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LastIPAddress { get; set; }
|
public string LastIPAddress { get; set; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user