Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
Leigh Pointer
2025-08-06 10:44:26 +02:00
13 changed files with 220 additions and 152 deletions

View File

@@ -153,7 +153,7 @@
<br /> <br />
<button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button> <button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) && PageState.Runtime != Shared.Runtime.Hybrid && !_ishost) @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) && PageState.Runtime != Shared.Runtime.Hybrid && !_ishost && _isdeleted != "True")
{ {
<button type="button" class="btn btn-primary ms-1" @onclick="ImpersonateUser">@Localizer["Impersonate"]</button> <button type="button" class="btn btn-primary ms-1" @onclick="ImpersonateUser">@Localizer["Impersonate"]</button>
} }

View File

@@ -17,8 +17,21 @@ else
{ {
<TabStrip> <TabStrip>
<TabPanel Name="Users" Heading="Users" ResourceKey="Users"> <TabPanel Name="Users" Heading="Users" ResourceKey="Users">
<ActionLink Action="Add" Text="Add User" Security="SecurityAccessLevel.Edit" ResourceKey="AddUser" />&nbsp; <div class="container">
<ActionLink Text="Import Users" Class="btn btn-secondary ms-2" Action="Users" Security="SecurityAccessLevel.Admin" ResourceKey="ImportUsers"/> <div class="row mb-1 align-items-center">
<div class="col-sm-6">
<ActionLink Action="Add" Text="Add User" Security="SecurityAccessLevel.Edit" ResourceKey="AddUser" />&nbsp;
<ActionLink Text="Import Users" Class="btn btn-secondary ms-2" Action="Users" Security="SecurityAccessLevel.Admin" ResourceKey="ImportUsers" />
</div>
<div class="col-sm-6">
<select id="deleted" class="form-select custom-select" value="@_deleted" @onchange="(e => DeletedChanged(e))">
<option value="false">@Localizer["Active Users"]</option>
<option value="true">@Localizer["Deleted Users"]</option>
</select>
</div>
</div>
</div>
<br />
<Pager Items="@users" RowClass="align-middle" SearchProperties="User.Username,User.Email,User.DisplayName"> <Pager Items="@users" RowClass="align-middle" SearchProperties="User.Username,User.Email,User.DisplayName">
<Header> <Header>
@@ -495,6 +508,7 @@ else
@code { @code {
private List<UserRole> users; private List<UserRole> users;
private string _deleted = "false";
private string _allowregistration; private string _allowregistration;
private string _registerurl; private string _registerurl;
@@ -564,7 +578,7 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await LoadUsersAsync(true); await LoadUsersAsync();
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_allowregistration = PageState.Site.AllowRegistration.ToString().ToLower(); _allowregistration = PageState.Site.AllowRegistration.ToString().ToLower();
@@ -636,20 +650,32 @@ else
_allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true"); _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
} }
private async Task LoadUsersAsync(bool load) private async Task LoadUsersAsync()
{ {
if (load) users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{ {
users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered); var hosts = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Host);
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) users.AddRange(hosts);
{ users = users.OrderBy(u => u.User.DisplayName).ToList();
var hosts = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Host);
users.AddRange(hosts);
users = users.OrderBy(u => u.User.DisplayName).ToList();
}
} }
users = users.Where(item => item.User.IsDeleted == bool.Parse(_deleted)).ToList();
} }
private async void DeletedChanged(ChangeEventArgs e)
{
try
{
_deleted = e.Value.ToString();
await LoadUsersAsync();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On DeletedChanged");
}
}
private async Task DeleteUser(UserRole UserRole) private async Task DeleteUser(UserRole UserRole)
{ {
try try
@@ -672,7 +698,7 @@ else
await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name); await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name);
} }
AddModuleMessage(Localizer["Success.DeleteUser"], MessageType.Success); AddModuleMessage(Localizer["Success.DeleteUser"], MessageType.Success);
await LoadUsersAsync(true); await LoadUsersAsync();
StateHasChanged(); StateHasChanged();
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -107,7 +107,7 @@
@code { @code {
private bool _initialized = false; private bool _initialized = false;
private List<Folder> _folders; private List<Folder> _folders = new List<Folder>();
private List<File> _files = new List<File>(); private List<File> _files = new List<File>();
private string _fileinputid = string.Empty; private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty; private string _progressinfoid = string.Empty;
@@ -198,19 +198,22 @@
Filter = "nupkg"; Filter = "nupkg";
ShowSuccess = true; ShowSuccess = true;
} }
else
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
{ {
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder); // folder path specified rather than folderid
if (folder != null) if (!string.IsNullOrEmpty(Folder))
{ {
FolderId = folder.FolderId; Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
} if (folder != null)
else {
{ FolderId = folder.FolderId;
FolderId = -1; }
_message = "Folder Path " + Folder + " Does Not Exist"; else
_messagetype = MessageType.Error; {
FolderId = -1;
_message = "Folder Path " + Folder + " Does Not Exist";
_messagetype = MessageType.Error;
}
} }
} }
@@ -245,25 +248,24 @@
} }
} }
await SetImage();
if (!string.IsNullOrEmpty(Filter)) if (!string.IsNullOrEmpty(Filter))
{ {
_filter = "." + Filter.Replace(",", ",."); _filter = "." + Filter.Replace(",", ",.");
} }
GetFolderPermission();
await SetImage();
await GetFiles(); await GetFiles();
_initialized = true; _initialized = true;
} }
private async Task GetFiles() private void GetFolderPermission()
{ {
_haseditpermission = false; _haseditpermission = false;
if (Folder == Constants.PackagesFolder) if (Folder == Constants.PackagesFolder)
{ {
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host); _haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
_files = new List<File>();
} }
else else
{ {
@@ -271,69 +273,14 @@
if (folder != null) if (folder != null)
{ {
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList); _haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Browse, folder.PermissionList))
{
_files = await FileService.GetFilesAsync(FolderId);
}
else
{
_files = new List<File>();
}
} }
else else
{ {
_haseditpermission = false; _haseditpermission = false;
_files = new List<File>();
}
if (_filter != "*")
{
List<File> filtered = new List<File>();
foreach (File file in _files)
{
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
{
filtered.Add(file);
}
}
_files = filtered;
} }
} }
} }
private async Task FolderChanged(ChangeEventArgs e)
{
_message = string.Empty;
try
{
FolderId = int.Parse((string)e.Value);
await GetFiles();
FileId = -1;
_file = null;
_image = string.Empty;
await OnSelectFolder.InvokeAsync(FolderId);
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
_message = Localizer["Error.File.Load"];
_messagetype = MessageType.Error;
}
}
private async Task FileChanged(ChangeEventArgs e)
{
_message = string.Empty;
FileId = int.Parse((string)e.Value);
await SetImage();
#pragma warning disable CS0618
await OnSelect.InvokeAsync(FileId);
#pragma warning restore CS0618
await OnSelectFile.InvokeAsync(FileId);
StateHasChanged();
}
private async Task SetImage() private async Task SetImage()
{ {
_image = string.Empty; _image = string.Empty;
@@ -357,6 +304,74 @@
} }
} }
private async Task GetFiles()
{
if (ShowFiles)
{
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
if (folder != null)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Browse, folder.PermissionList))
{
_files = await FileService.GetFilesAsync(FolderId);
}
else
{
_files = new List<File>();
}
}
else
{
_files = new List<File>();
}
if (_filter != "*")
{
List<File> filtered = new List<File>();
foreach (File file in _files)
{
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
{
filtered.Add(file);
}
}
_files = filtered;
}
}
}
private async Task FolderChanged(ChangeEventArgs e)
{
_message = string.Empty;
try
{
FolderId = int.Parse((string)e.Value);
await OnSelectFolder.InvokeAsync(FolderId);
FileId = -1;
GetFolderPermission();
await SetImage();
await GetFiles();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
_message = Localizer["Error.File.Load"];
_messagetype = MessageType.Error;
}
}
private async Task FileChanged(ChangeEventArgs e)
{
_message = string.Empty;
FileId = int.Parse((string)e.Value);
#pragma warning disable CS0618
await OnSelect.InvokeAsync(FileId);
#pragma warning restore CS0618
await OnSelectFile.InvokeAsync(FileId);
await SetImage();
StateHasChanged();
}
private async Task UploadFiles() private async Task UploadFiles()
{ {
_message = string.Empty; _message = string.Empty;
@@ -433,6 +448,27 @@
_message = Localizer["Success.File.Upload"]; _message = Localizer["Success.File.Upload"];
_messagetype = MessageType.Success; _messagetype = MessageType.Success;
} }
FileId = -1;
if (Folder != Constants.PackagesFolder && !AnonymizeUploadFilenames)
{
// set FileId to first file in upload collection
var file = await FileService.GetFileAsync(int.Parse(folder), uploads[0].Split(":")[0]);
if (file != null)
{
FileId = file.FileId;
}
}
await OnUpload.InvokeAsync(FileId);
#pragma warning disable CS0618
await OnSelect.InvokeAsync(FileId);
#pragma warning restore CS0618
await OnSelectFile.InvokeAsync(FileId);
await SetImage();
await GetFiles();
StateHasChanged();
} }
else else
{ {
@@ -440,28 +476,6 @@
_message = Localizer["Error.File.Upload"]; _message = Localizer["Error.File.Upload"];
_messagetype = MessageType.Error; _messagetype = MessageType.Error;
} }
if (Folder == Constants.PackagesFolder)
{
await OnUpload.InvokeAsync(-1);
}
else
{
// set FileId to first file in upload collection
var file = await FileService.GetFileAsync(int.Parse(folder), uploads[0].Split(":")[0]);
if (file != null)
{
FileId = file.FileId;
await SetImage();
#pragma warning disable CS0618
await OnSelect.InvokeAsync(FileId);
#pragma warning restore CS0618
await OnSelectFile.InvokeAsync(FileId);
await OnUpload.InvokeAsync(FileId);
}
await GetFiles();
StateHasChanged();
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -474,7 +488,6 @@
finally { finally {
tokenSource.Dispose(); tokenSource.Dispose();
} }
} }
else else
{ {
@@ -504,47 +517,49 @@
_messagetype = MessageType.Success; _messagetype = MessageType.Success;
} }
await GetFiles(); FileId = -1;
FileId = -1;
await SetImage();
#pragma warning disable CS0618 #pragma warning disable CS0618
await OnSelect.InvokeAsync(FileId); await OnSelect.InvokeAsync(FileId);
#pragma warning restore CS0618 #pragma warning restore CS0618
await OnSelectFile.InvokeAsync(FileId); await OnSelectFile.InvokeAsync(FileId);
await SetImage();
await GetFiles();
StateHasChanged(); StateHasChanged();
} }
catch (Exception ex) catch (Exception ex)
{ {
await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message); await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
_message = Localizer["Error.File.Delete"]; _message = Localizer["Error.File.Delete"];
_messagetype = MessageType.Error; _messagetype = MessageType.Error;
} }
} }
public int GetFileId() => FileId; public int GetFileId() => FileId;
public int GetFolderId() => FolderId; public int GetFolderId() => FolderId;
public File GetFile() => _file; public File GetFile() => _file;
public async Task Refresh() public async Task Refresh()
{ {
await Refresh(-1); await Refresh(-1);
} }
public async Task Refresh(int fileId) public async Task Refresh(int fileId)
{ {
await GetFiles(); await GetFiles();
if (fileId != -1) FileId = -1;
if (fileId != -1)
{ {
var file = _files.Where(item => item.FileId == fileId).FirstOrDefault(); var file = _files.Where(item => item.FileId == fileId).FirstOrDefault();
if (file != null) if (file != null)
{ {
FileId = file.FileId; FileId = file.FileId;
await SetImage();
} }
} }
StateHasChanged(); await SetImage();
StateHasChanged();
} }
} }

View File

@@ -537,4 +537,10 @@
<data name="AllowHostRole.HelpText" xml:space="preserve"> <data name="AllowHostRole.HelpText" xml:space="preserve">
<value>Indicate if host roles are supported from the identity provider. Please use caution with this option as it allows the host user to administrate every site within your installation.</value> <value>Indicate if host roles are supported from the identity provider. Please use caution with this option as it allows the host user to administrate every site within your installation.</value>
</data> </data>
<data name="Active Users" xml:space="preserve">
<value>Active Users</value>
</data>
<data name="Deleted Users" xml:space="preserve">
<value>Deleted Users</value>
</data>
</root> </root>

View File

@@ -64,8 +64,6 @@
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
_messageContent = "";
if (ShouldRender()) if (ShouldRender())
{ {
if (!string.IsNullOrEmpty(ModuleState.ModuleType)) if (!string.IsNullOrEmpty(ModuleState.ModuleType))
@@ -107,7 +105,7 @@
public void AddModuleMessage(string message, MessageType type, string position) public void AddModuleMessage(string message, MessageType type, string position)
{ {
if(message != _messageContent if (message != _messageContent
|| type != _messageType || type != _messageType
|| position != _messagePosition) || position != _messagePosition)
{ {

View File

@@ -48,7 +48,7 @@
private bool _initialized = false; private bool _initialized = false;
private bool _installed = false; private bool _installed = false;
private string _display = "display: none;"; // prevents flash on initial interactive page load when using prerendering private string _display = "display: none;"; // prevents flash on initial interactive page load
private PageState _pageState { get; set; } private PageState _pageState { get; set; }
@@ -83,10 +83,10 @@
protected override void OnAfterRender(bool firstRender) protected override void OnAfterRender(bool firstRender)
{ {
if (firstRender && _display == "display: none;") if (firstRender)
{ {
_display = ""; _display = "";
StateHasChanged(); // required or else the UI will not refresh StateHasChanged();
} }
} }

View File

@@ -298,7 +298,7 @@ namespace Oqtane.Controllers
if (!authorized) if (!authorized)
{ {
var visitorCookieName = Constants.VisitorCookiePrefix + _alias.SiteId.ToString(); var visitorCookieName = Constants.VisitorCookiePrefix + _alias.SiteId.ToString();
authorized = (entityId == GetVisitorCookieId(Request.Cookies[visitorCookieName])); authorized = (entityId == GetVisitorCookieId(HttpContext.Request.Cookies[visitorCookieName]));
} }
break; break;
default: // custom entity default: // custom entity
@@ -352,9 +352,14 @@ namespace Oqtane.Controllers
private int GetVisitorCookieId(string visitorCookie) private int GetVisitorCookieId(string visitorCookie)
{ {
// visitor cookies contain the visitor id and an expiry date separated by a pipe symbol var visitorId = -1;
visitorCookie = (visitorCookie.Contains("|")) ? visitorCookie.Split('|')[0] : visitorCookie; if (visitorCookie != null)
return (int.TryParse(visitorCookie, out int visitorId)) ? visitorId : -1; {
// visitor cookies now contain the visitor id and an expiry date separated by a pipe symbol
visitorCookie = (visitorCookie.Contains("|")) ? visitorCookie.Split('|')[0] : visitorCookie;
visitorId = int.TryParse(visitorCookie, out int _visitorId) ? _visitorId : -1;
}
return visitorId;
} }
private void AddSyncEvent(string EntityName, int EntityId, int SettingId, string Action) private void AddSyncEvent(string EntityName, int EntityId, int SettingId, string Action)

View File

@@ -77,9 +77,14 @@ namespace Oqtane.Controllers
private int GetVisitorCookieId(string visitorCookie) private int GetVisitorCookieId(string visitorCookie)
{ {
// visitor cookies contain the visitor id and an expiry date separated by a pipe symbol var visitorId = -1;
visitorCookie = (visitorCookie.Contains("|")) ? visitorCookie.Split('|')[0] : visitorCookie; if (visitorCookie != null)
return (int.TryParse(visitorCookie, out int visitorId)) ? visitorId : -1; {
// visitor cookies now contain the visitor id and an expiry date separated by a pipe symbol
visitorCookie = (visitorCookie.Contains("|")) ? visitorCookie.Split('|')[0] : visitorCookie;
visitorId = int.TryParse(visitorCookie, out int _visitorId) ? _visitorId : -1;
}
return visitorId;
} }
} }
} }

View File

@@ -257,7 +257,7 @@ namespace Microsoft.Extensions.DependencyInjection
// set the cookies to allow HttpClient API calls to be authenticated // set the cookies to allow HttpClient API calls to be authenticated
foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies) foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies)
{ {
client.DefaultRequestHeaders.Add("Cookie", cookie.Key + "=" + cookie.Value); client.DefaultRequestHeaders.Add("Cookie", cookie.Key + "=" + WebUtility.UrlEncode(cookie.Value));
} }
} }
@@ -275,7 +275,7 @@ namespace Microsoft.Extensions.DependencyInjection
// set the cookies to allow HttpClient API calls to be authenticated // set the cookies to allow HttpClient API calls to be authenticated
foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies) foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies)
{ {
client.DefaultRequestHeaders.Add("Cookie", cookie.Key + "=" + cookie.Value); client.DefaultRequestHeaders.Add("Cookie", cookie.Key + "=" + WebUtility.UrlEncode(cookie.Value));
} }
} }
}); });

View File

@@ -261,7 +261,8 @@ namespace Oqtane.Managers
var emailConfirmationToken = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); var emailConfirmationToken = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
await _identityUserManager.ConfirmEmailAsync(identityuser, emailConfirmationToken); await _identityUserManager.ConfirmEmailAsync(identityuser, emailConfirmationToken);
string body = "Dear " + user.DisplayName + ",\n\nThe Email Address For Your User Account Has Been Verified. You Can Now Login With Your Username And Password."; string url = alias.Protocol + alias.Name + "/login?name=" + user.Username;
string body = "Dear " + user.DisplayName + ",\n\nThe Email Address For Your User Account Has Been Verified. You Can Now Login With Your Username And Password Using The Link Displayed Below:\n\n" + url + "\n\nThank You!";
var notification = new Notification(user.SiteId, user, "User Account Verification", body); var notification = new Notification(user.SiteId, user, "User Account Verification", body);
_notifications.AddNotification(notification); _notifications.AddNotification(notification);
} }

View File

@@ -36,7 +36,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.7" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.7" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
@@ -46,7 +46,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.7" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.7" /> <PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.7" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.11" /> <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.11" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.10" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="HtmlAgilityPack" Version="1.12.2" /> <PackageReference Include="HtmlAgilityPack" Version="1.12.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageReference Include="MailKit" Version="4.13.0" /> <PackageReference Include="MailKit" Version="4.13.0" />

View File

@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Oqtane.Enums;
using Oqtane.Extensions; using Oqtane.Extensions;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Managers; using Oqtane.Managers;
@@ -16,11 +17,13 @@ namespace Oqtane.Pages
{ {
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly ISyncManager _syncManager; private readonly ISyncManager _syncManager;
private readonly ILogManager _logger;
public LogoutModel(IUserManager userManager, ISyncManager syncManager) public LogoutModel(IUserManager userManager, ISyncManager syncManager, ILogManager logger)
{ {
_userManager = userManager; _userManager = userManager;
_syncManager = syncManager; _syncManager = syncManager;
_logger = logger;
} }
public async Task<IActionResult> OnPostAsync(string returnurl, string everywhere) public async Task<IActionResult> OnPostAsync(string returnurl, string everywhere)
@@ -37,6 +40,7 @@ namespace Oqtane.Pages
} }
_syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, "Logout"); _syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, "Logout");
_syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, SyncEventActions.Reload); _syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, SyncEventActions.Reload);
_logger.Log(LogLevel.Information, this, LogFunction.Security, "User Logout For Username {Username}", user.Username);
} }
await HttpContext.SignOutAsync(Constants.AuthenticationScheme); await HttpContext.SignOutAsync(Constants.AuthenticationScheme);

View File

@@ -68,6 +68,7 @@ namespace Oqtane.Repository
public UrlMapping GetUrlMapping(int siteId, string url) public UrlMapping GetUrlMapping(int siteId, string url)
{ {
using var db = _dbContextFactory.CreateDbContext(); using var db = _dbContextFactory.CreateDbContext();
url = (url.StartsWith("/")) ? url.Substring(1) : url;
url = (url.Length > 750) ? url.Substring(0, 750) : url; url = (url.Length > 750) ? url.Substring(0, 750) : url;
var urlMapping = db.UrlMapping.Where(item => item.SiteId == siteId && item.Url == url).FirstOrDefault(); var urlMapping = db.UrlMapping.Where(item => item.SiteId == siteId && item.Url == url).FirstOrDefault();
if (urlMapping == null) if (urlMapping == null)
@@ -82,7 +83,14 @@ namespace Oqtane.Repository
urlMapping.Requests = 1; urlMapping.Requests = 1;
urlMapping.CreatedOn = DateTime.UtcNow; urlMapping.CreatedOn = DateTime.UtcNow;
urlMapping.RequestedOn = DateTime.UtcNow; urlMapping.RequestedOn = DateTime.UtcNow;
urlMapping = AddUrlMapping(urlMapping); try
{
urlMapping = AddUrlMapping(urlMapping);
}
catch
{
// ignore duplicate key exception which can be caused by a race condition
}
} }
} }
else else