breaking search modifications into smaller PRs

This commit is contained in:
sbwalker 2024-06-28 15:43:54 -04:00
parent 22063248ca
commit 0178e015e3
9 changed files with 89 additions and 57 deletions

View File

@ -95,19 +95,15 @@ namespace Oqtane.Managers.Search
searchContent.EntityName = EntityNames.Module; searchContent.EntityName = EntityNames.Module;
} }
if(searchContent.EntityId == 0) if(string.IsNullOrEmpty(searchContent.EntityId))
{ {
searchContent.EntityId = pageModule.ModuleId; searchContent.EntityId = pageModule.ModuleId.ToString();
} }
if (searchContent.IsActive)
{
searchContent.IsActive = !pageModule.Module.IsDeleted;
}
if (searchContent.ModifiedTime == DateTime.MinValue) if (searchContent.ContentModifiedOn == DateTime.MinValue)
{ {
searchContent.ModifiedTime = pageModule.ModifiedOn; searchContent.ContentModifiedOn = pageModule.ModifiedOn;
} }
if (string.IsNullOrEmpty(searchContent.AdditionalContent)) if (string.IsNullOrEmpty(searchContent.AdditionalContent))

View File

@ -48,16 +48,18 @@ namespace Oqtane.Managers.Search
var searchContent = new SearchContent var searchContent = new SearchContent
{ {
EntityName = EntityNames.Page,
EntityId = page.PageId,
SiteId = page.SiteId, SiteId = page.SiteId,
ModifiedTime = page.ModifiedOn, EntityName = EntityNames.Page,
AdditionalContent = string.Empty, EntityId = page.PageId.ToString(),
Url = $"{(!string.IsNullOrEmpty(page.Path) && !page.Path.StartsWith("/") ? "/" : "")}{page.Path}",
Title = !string.IsNullOrEmpty(page.Title) ? page.Title : page.Name, Title = !string.IsNullOrEmpty(page.Title) ? page.Title : page.Name,
Description = string.Empty, Description = string.Empty,
Body = $"{page.Name} {page.Title}", Body = $"{page.Name} {page.Title}",
IsActive = !page.IsDeleted && Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) Url = $"{(!string.IsNullOrEmpty(page.Path) && !page.Path.StartsWith("/") ? "/" : "")}{page.Path}",
Permissions = $"{EntityNames.Page}:{page.PageId}",
ContentModifiedBy = page.ModifiedBy,
ContentModifiedOn = page.ModifiedOn,
AdditionalContent = string.Empty,
CreatedOn = DateTime.UtcNow
}; };
if (searchContent.SearchContentProperties == null) if (searchContent.SearchContentProperties == null)

View File

@ -2,11 +2,10 @@ using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using Oqtane.Databases.Interfaces; using Oqtane.Databases.Interfaces;
using Oqtane.Models;
namespace Oqtane.Migrations.EntityBuilders namespace Oqtane.Migrations.EntityBuilders
{ {
public class SearchContentEntityBuilder : AuditableBaseEntityBuilder<SearchContentEntityBuilder> public class SearchContentEntityBuilder : BaseEntityBuilder<SearchContentEntityBuilder>
{ {
private const string _entityTableName = "SearchContent"; private const string _entityTableName = "SearchContent";
private readonly PrimaryKey<SearchContentEntityBuilder> _primaryKey = new("PK_SearchContent", x => x.SearchContentId); private readonly PrimaryKey<SearchContentEntityBuilder> _primaryKey = new("PK_SearchContent", x => x.SearchContentId);
@ -20,30 +19,30 @@ namespace Oqtane.Migrations.EntityBuilders
protected override SearchContentEntityBuilder BuildTable(ColumnsBuilder table) protected override SearchContentEntityBuilder BuildTable(ColumnsBuilder table)
{ {
SearchContentId = AddAutoIncrementColumn(table, "SearchContentId"); SearchContentId = AddAutoIncrementColumn(table, "SearchContentId");
SiteId = AddIntegerColumn(table, "SiteId");
EntityName = AddStringColumn(table, "EntityName", 50); EntityName = AddStringColumn(table, "EntityName", 50);
EntityId = AddIntegerColumn(table, "EntityId"); EntityId = AddIntegerColumn(table, "EntityId");
SiteId = AddIntegerColumn(table, "SiteId"); Title = AddStringColumn(table, "Title", 200);
Title = AddStringColumn(table, "Title", 255);
Description = AddMaxStringColumn(table, "Description"); Description = AddMaxStringColumn(table, "Description");
Body = AddMaxStringColumn(table, "Body"); Body = AddMaxStringColumn(table, "Body");
Url = AddStringColumn(table, "Url", 255); Url = AddStringColumn(table, "Url", 500);
ModifiedTime = AddDateTimeColumn(table, "ModifiedTime"); Permissions = AddStringColumn(table, "Permissions", 100);
IsActive = AddBooleanColumn(table, "IsActive"); ContentModifiedBy = AddStringColumn(table, "ContentModifiedBy", 256);
ContentModifiedOn = AddDateTimeColumn(table, "ContentModifiedOn");
AdditionalContent = AddMaxStringColumn(table, "AdditionalContent"); AdditionalContent = AddMaxStringColumn(table, "AdditionalContent");
CreatedOn = AddDateTimeColumn(table, "CreatedOn");
AddAuditableColumns(table);
return this; return this;
} }
public OperationBuilder<AddColumnOperation> SearchContentId { get; private set; } public OperationBuilder<AddColumnOperation> SearchContentId { get; private set; }
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
public OperationBuilder<AddColumnOperation> EntityName { get; private set; } public OperationBuilder<AddColumnOperation> EntityName { get; private set; }
public OperationBuilder<AddColumnOperation> EntityId { get; private set; } public OperationBuilder<AddColumnOperation> EntityId { get; private set; }
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
public OperationBuilder<AddColumnOperation> Title { get; private set; } public OperationBuilder<AddColumnOperation> Title { get; private set; }
public OperationBuilder<AddColumnOperation> Description { get; private set; } public OperationBuilder<AddColumnOperation> Description { get; private set; }
@ -52,10 +51,14 @@ namespace Oqtane.Migrations.EntityBuilders
public OperationBuilder<AddColumnOperation> Url { get; private set; } public OperationBuilder<AddColumnOperation> Url { get; private set; }
public OperationBuilder<AddColumnOperation> ModifiedTime { get; private set; } public OperationBuilder<AddColumnOperation> Permissions { get; private set; }
public OperationBuilder<AddColumnOperation> IsActive { get; private set; } public OperationBuilder<AddColumnOperation> ContentModifiedBy { get; private set; }
public OperationBuilder<AddColumnOperation> ContentModifiedOn { get; private set; }
public OperationBuilder<AddColumnOperation> AdditionalContent { get; private set; } public OperationBuilder<AddColumnOperation> AdditionalContent { get; private set; }
public OperationBuilder<AddColumnOperation> CreatedOn { get; private set; }
} }
} }

View File

@ -62,7 +62,8 @@ namespace Oqtane.Modules.HtmlText.Manager
Title = module.Title, Title = module.Title,
Description = string.Empty, Description = string.Empty,
Body = htmltext.Content, Body = htmltext.Content,
ModifiedTime = htmltext.ModifiedOn ContentModifiedBy = htmltext.ModifiedBy,
ContentModifiedOn = htmltext.ModifiedOn
}); });
} }

View File

@ -74,13 +74,13 @@ namespace Oqtane.Providers
switch (searchQuery.SortField) switch (searchQuery.SortField)
{ {
case SearchSortFields.Relevance: case SearchSortFields.Relevance:
results = results.OrderByDescending(i => i.Score).ThenByDescending(i => i.ModifiedTime); results = results.OrderByDescending(i => i.Score).ThenByDescending(i => i.ContentModifiedOn);
break; break;
case SearchSortFields.Title: case SearchSortFields.Title:
results = results.OrderByDescending(i => i.Title).ThenByDescending(i => i.ModifiedTime); results = results.OrderByDescending(i => i.Title).ThenByDescending(i => i.ContentModifiedOn);
break; break;
default: default:
results = results.OrderByDescending(i => i.ModifiedTime); results = results.OrderByDescending(i => i.ContentModifiedOn);
break; break;
} }
} }
@ -89,13 +89,13 @@ namespace Oqtane.Providers
switch (searchQuery.SortField) switch (searchQuery.SortField)
{ {
case SearchSortFields.Relevance: case SearchSortFields.Relevance:
results = results.OrderBy(i => i.Score).ThenByDescending(i => i.ModifiedTime); results = results.OrderBy(i => i.Score).ThenByDescending(i => i.ContentModifiedOn);
break; break;
case SearchSortFields.Title: case SearchSortFields.Title:
results = results.OrderBy(i => i.Title).ThenByDescending(i => i.ModifiedTime); results = results.OrderBy(i => i.Title).ThenByDescending(i => i.ContentModifiedOn);
break; break;
default: default:
results = results.OrderBy(i => i.ModifiedTime); results = results.OrderBy(i => i.ContentModifiedOn);
break; break;
} }
} }
@ -135,7 +135,9 @@ namespace Oqtane.Providers
Description = searchContent.Description, Description = searchContent.Description,
Body = searchContent.Body, Body = searchContent.Body,
Url = searchContent.Url, Url = searchContent.Url,
ModifiedTime = searchContent.ModifiedTime, Permissions = searchContent.Permissions,
ContentModifiedBy = searchContent.ContentModifiedBy,
ContentModifiedOn = searchContent.ContentModifiedOn,
SearchContentProperties = searchContent.SearchContentProperties, SearchContentProperties = searchContent.SearchContentProperties,
Snippet = BuildSnippet(searchContent, searchQuery), Snippet = BuildSnippet(searchContent, searchQuery),
Score = CalculateScore(searchContent, searchQuery) Score = CalculateScore(searchContent, searchQuery)

View File

@ -10,7 +10,7 @@ namespace Oqtane.Repository
Task<IEnumerable<SearchContent>> GetSearchContentsAsync(SearchQuery searchQuery); Task<IEnumerable<SearchContent>> GetSearchContentsAsync(SearchQuery searchQuery);
SearchContent AddSearchContent(SearchContent searchContent); SearchContent AddSearchContent(SearchContent searchContent);
void DeleteSearchContent(int searchContentId); void DeleteSearchContent(int searchContentId);
void DeleteSearchContent(string entityName, int entryId); void DeleteSearchContent(string entityName, string entryId);
void DeleteSearchContent(string uniqueKey); void DeleteSearchContent(string uniqueKey);
void DeleteAllSearchContent(); void DeleteAllSearchContent();

View File

@ -24,7 +24,7 @@ namespace Oqtane.Repository
.Include(i => i.SearchContentProperties) .Include(i => i.SearchContentProperties)
.Include(i => i.SearchContentWords) .Include(i => i.SearchContentWords)
.ThenInclude(w => w.SearchWord) .ThenInclude(w => w.SearchWord)
.Where(i => i.SiteId == searchQuery.SiteId && i.IsActive); .Where(i => i.SiteId == searchQuery.SiteId);
if (searchQuery.EntityNames != null && searchQuery.EntityNames.Any()) if (searchQuery.EntityNames != null && searchQuery.EntityNames.Any())
{ {
@ -33,12 +33,12 @@ namespace Oqtane.Repository
if (searchQuery.BeginModifiedTimeUtc != DateTime.MinValue) if (searchQuery.BeginModifiedTimeUtc != DateTime.MinValue)
{ {
searchContents = searchContents.Where(i => i.ModifiedTime >= searchQuery.BeginModifiedTimeUtc); searchContents = searchContents.Where(i => i.ContentModifiedOn >= searchQuery.BeginModifiedTimeUtc);
} }
if (searchQuery.EndModifiedTimeUtc != DateTime.MinValue) if (searchQuery.EndModifiedTimeUtc != DateTime.MinValue)
{ {
searchContents = searchContents.Where(i => i.ModifiedTime <= searchQuery.EndModifiedTimeUtc); searchContents = searchContents.Where(i => i.ContentModifiedOn <= searchQuery.EndModifiedTimeUtc);
} }
if (searchQuery.Properties != null && searchQuery.Properties.Any()) if (searchQuery.Properties != null && searchQuery.Properties.Any())
@ -88,7 +88,7 @@ namespace Oqtane.Repository
db.SaveChanges(); db.SaveChanges();
} }
public void DeleteSearchContent(string entityName, int entryId) public void DeleteSearchContent(string entityName, string entryId)
{ {
using var db = _dbContextFactory.CreateDbContext(); using var db = _dbContextFactory.CreateDbContext();
var searchContent = db.SearchContent.FirstOrDefault(i => i.EntityName == entityName && i.EntityId == entryId); var searchContent = db.SearchContent.FirstOrDefault(i => i.EntityName == entityName && i.EntityId == entryId);

View File

@ -10,6 +10,7 @@ using Oqtane.Models;
using Oqtane.Repository; using Oqtane.Repository;
using Oqtane.Security; using Oqtane.Security;
using Oqtane.Shared; using Oqtane.Shared;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace Oqtane.Services namespace Oqtane.Services
{ {
@ -199,17 +200,18 @@ namespace Oqtane.Services
private bool Visible(SearchContent searchContent, SearchQuery searchQuery) private bool Visible(SearchContent searchContent, SearchQuery searchQuery)
{ {
if(!HasViewPermission(searchQuery.SiteId, searchQuery.User, searchContent.EntityName, searchContent.EntityId)) var visible = true;
foreach (var permission in searchContent.Permissions.Split(','))
{ {
return false; var entityName = permission.Split(":")[0];
} var entityId = int.Parse(permission.Split(":")[1]);
if (!HasViewPermission(searchQuery.SiteId, searchQuery.User, entityName, entityId))
var searchResultManager = GetSearchResultManagers().FirstOrDefault(i => i.Name == searchContent.EntityName);
if (searchResultManager != null)
{ {
return searchResultManager.Visible(searchContent, searchQuery); visible = false;
break;
} }
return true; }
return visible;
} }
private bool HasViewPermission(int siteId, User user, string entityName, int entityId) private bool HasViewPermission(int siteId, User user, string entityName, int entityId)

View File

@ -4,18 +4,15 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json; using System.Text.Json;
namespace Oqtane.Models namespace Oqtane.Models
{ {
public class SearchContent : ModelBase public class SearchContent
{ {
public int SearchContentId { get; set; } public int SearchContentId { get; set; }
[NotMapped] public int SiteId { get; set; }
public string UniqueKey => $"{EntityName}:{EntityId}";
public string EntityName { get; set; } public string EntityName { get; set; }
public int EntityId { get; set; } public string EntityId { get; set; }
public int SiteId { get; set; }
public string Title { get; set; } public string Title { get; set; }
@ -25,16 +22,45 @@ namespace Oqtane.Models
public string Url { get; set; } public string Url { get; set; }
public DateTime ModifiedTime { get; set; } public string Permissions { get; set; }
public bool IsActive { get; set; } = true; public string ContentModifiedBy { get; set; }
public DateTime ContentModifiedOn { get; set; }
public string AdditionalContent { get; set; } public string AdditionalContent { get; set; }
public DateTime CreatedOn { get; set; }
public List<SearchContentProperty> SearchContentProperties { get; set; } public List<SearchContentProperty> SearchContentProperties { get; set; }
public List<SearchContentWord> SearchContentWords { get; set; } public List<SearchContentWord> SearchContentWords { get; set; }
[NotMapped]
public string UniqueKey => $"{EntityName}:{EntityId}";
[NotMapped]
public int TenantId { get; set; }
// constructors
public SearchContent() { }
public SearchContent(int siteId, string entityName, string entityId, string title, string description, string body, string url, string permissions, string contentModifiedBy, DateTime contentModifiedOn)
{
SiteId = siteId;
EntityName = entityName;
EntityId = entityId;
Title = title;
Description = description;
Body = body;
Url = url;
Permissions = permissions;
ContentModifiedBy = contentModifiedBy;
ContentModifiedOn = contentModifiedOn;
AdditionalContent = "";
CreatedOn = DateTime.UtcNow;
}
public override string ToString() public override string ToString()
{ {
return JsonSerializer.Serialize(this); return JsonSerializer.Serialize(this);