resolve security issue in Search

This commit is contained in:
sbwalker 2024-07-15 10:07:48 -04:00
parent 6275ab23ff
commit 17fec7d6e1
4 changed files with 16 additions and 31 deletions

View File

@ -100,7 +100,6 @@
{ {
SiteId = PageState.Site.SiteId, SiteId = PageState.Site.SiteId,
Alias = PageState.Alias, Alias = PageState.Alias,
User = PageState.User,
Keywords = _keywords, Keywords = _keywords,
SortDirection = _searchSortDirection, SortDirection = _searchSortDirection,
SortField = _searchSortField, SortField = _searchSortField,

View File

@ -97,7 +97,7 @@ namespace Oqtane.Infrastructure
ContentModifiedOn = page.ModifiedOn, ContentModifiedOn = page.ModifiedOn,
AdditionalContent = string.Empty, AdditionalContent = string.Empty,
CreatedOn = DateTime.UtcNow, CreatedOn = DateTime.UtcNow,
IsDeleted = (removed || pageModules.Any(item => item.PageId == page.PageId)), IsDeleted = removed,
TenantId = tenantId TenantId = tenantId
}; };
searchContents.Add(searchContent); searchContents.Add(searchContent);

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Oqtane.Models; using Oqtane.Models;
using Oqtane.Repository; using Oqtane.Repository;
@ -16,16 +17,20 @@ namespace Oqtane.Services
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly ISettingRepository _settingRepository; private readonly ISettingRepository _settingRepository;
private readonly IPermissionRepository _permissionRepository; private readonly IUserPermissions _userPermissions;
private readonly IHttpContextAccessor _accessor;
public SearchService( public SearchService(
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
ISettingRepository settingRepository, ISettingRepository settingRepository,
IPermissionRepository permissionRepository) IUserPermissions userPermissions,
IHttpContextAccessor accessor)
{ {
_settingRepository = settingRepository; _settingRepository = settingRepository;
_permissionRepository = permissionRepository;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_userPermissions = userPermissions;
_accessor = accessor;
} }
public async Task<SearchResults> GetSearchResultsAsync(SearchQuery searchQuery) public async Task<SearchResults> GetSearchResultsAsync(SearchQuery searchQuery)
@ -35,9 +40,12 @@ namespace Oqtane.Services
var totalResults = 0; var totalResults = 0;
// trim results based on permissions // trim results
var results = searchResults.Where(i => IsVisible(i, searchQuery)); var results = searchResults.Where(i => HasViewPermission(i, searchQuery))
.OrderBy(i => i.Url).ThenByDescending(i => i.Score)
.DistinctBy(i => i.Url);
// sort results
if (searchQuery.SortDirection == SearchSortDirections.Descending) if (searchQuery.SortDirection == SearchSortDirections.Descending)
{ {
switch (searchQuery.SortField) switch (searchQuery.SortField)
@ -69,20 +77,6 @@ namespace Oqtane.Services
} }
} }
// remove duplicated results based on page id for Page and Module types
results = results.DistinctBy(i =>
{
if (i.EntityName == EntityNames.Page || i.EntityName == EntityNames.Module)
{
var pageId = i.SearchContentProperties.FirstOrDefault(p => p.Name == Constants.SearchPageIdPropertyName)?.Value ?? string.Empty;
return !string.IsNullOrEmpty(pageId) ? pageId : i.UniqueKey;
}
else
{
return i.UniqueKey;
}
});
totalResults = results.Count(); totalResults = results.Count();
return new SearchResults return new SearchResults
@ -92,14 +86,14 @@ namespace Oqtane.Services
}; };
} }
private bool IsVisible(SearchContent searchContent, SearchQuery searchQuery) private bool HasViewPermission(SearchContent searchContent, SearchQuery searchQuery)
{ {
var visible = true; var visible = true;
foreach (var permission in searchContent.Permissions.Split(',')) foreach (var permission in searchContent.Permissions.Split(','))
{ {
var entityName = permission.Split(":")[0]; var entityName = permission.Split(":")[0];
var entityId = int.Parse(permission.Split(":")[1]); var entityId = int.Parse(permission.Split(":")[1]);
if (!HasViewPermission(searchQuery.SiteId, searchQuery.User, entityName, entityId)) if (!_userPermissions.IsAuthorized(_accessor.HttpContext.User, searchQuery.SiteId, entityName, entityId, PermissionNames.View))
{ {
visible = false; visible = false;
break; break;
@ -108,12 +102,6 @@ namespace Oqtane.Services
return visible; return visible;
} }
private bool HasViewPermission(int siteId, User user, string entityName, int entityId)
{
var permissions = _permissionRepository.GetPermissions(siteId, entityName, entityId).ToList();
return UserSecurity.IsAuthorized(user, PermissionNames.View, permissions);
}
public async Task<string> SaveSearchContentsAsync(List<SearchContent> searchContents, Dictionary<string, string> siteSettings) public async Task<string> SaveSearchContentsAsync(List<SearchContent> searchContents, Dictionary<string, string> siteSettings)
{ {
var result = ""; var result = "";

View File

@ -10,8 +10,6 @@ namespace Oqtane.Models
public Alias Alias { get; set; } public Alias Alias { get; set; }
public User User { get; set; }
public string Keywords { get; set; } public string Keywords { get; set; }
public List<string> EntityNames { get; set; } = new List<string>(); public List<string> EntityNames { get; set; } = new List<string>();