-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main' into ma/dispose-async
- Loading branch information
Showing
17 changed files
with
320 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 86 additions & 42 deletions
128
...hardCore.Modules/OrchardCore.Search.Elasticsearch/Drivers/ElasticSettingsDisplayDriver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,119 @@ | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Localization; | ||
using Nest; | ||
using OrchardCore.DisplayManagement.Entities; | ||
using OrchardCore.DisplayManagement.Handlers; | ||
using OrchardCore.DisplayManagement.Views; | ||
using OrchardCore.Mvc.ModelBinding; | ||
using OrchardCore.Search.Elasticsearch.Core.Models; | ||
using OrchardCore.Search.Elasticsearch.Core.Services; | ||
using OrchardCore.Search.Elasticsearch.ViewModels; | ||
using OrchardCore.Settings; | ||
|
||
namespace OrchardCore.Search.Elasticsearch.Drivers | ||
namespace OrchardCore.Search.Elasticsearch.Drivers; | ||
|
||
public class ElasticSettingsDisplayDriver : SectionDisplayDriver<ISite, ElasticSettings> | ||
{ | ||
public class ElasticSettingsDisplayDriver : SectionDisplayDriver<ISite, ElasticSettings> | ||
public const string GroupId = "elasticsearch"; | ||
|
||
private static readonly char[] _separator = [',', ' ']; | ||
private static readonly JsonSerializerOptions _jsonSerializerOptions = new() | ||
{ | ||
WriteIndented = true, | ||
}; | ||
private readonly ElasticIndexSettingsService _elasticIndexSettingsService; | ||
private readonly IHttpContextAccessor _httpContextAccessor; | ||
private readonly IAuthorizationService _authorizationService; | ||
private readonly IElasticClient _elasticClient; | ||
protected readonly IStringLocalizer S; | ||
|
||
public ElasticSettingsDisplayDriver( | ||
ElasticIndexSettingsService elasticIndexSettingsService, | ||
IHttpContextAccessor httpContextAccessor, | ||
IAuthorizationService authorizationService, | ||
IElasticClient elasticClient, | ||
IStringLocalizer<ElasticSettingsDisplayDriver> stringLocalizer | ||
) | ||
{ | ||
public const string GroupId = "elasticsearch"; | ||
private readonly ElasticIndexSettingsService _elasticIndexSettingsService; | ||
private readonly IHttpContextAccessor _httpContextAccessor; | ||
private readonly IAuthorizationService _authorizationService; | ||
_elasticIndexSettingsService = elasticIndexSettingsService; | ||
_httpContextAccessor = httpContextAccessor; | ||
_authorizationService = authorizationService; | ||
_elasticClient = elasticClient; | ||
S = stringLocalizer; | ||
} | ||
|
||
public ElasticSettingsDisplayDriver( | ||
ElasticIndexSettingsService elasticIndexSettingsService, | ||
IHttpContextAccessor httpContextAccessor, | ||
IAuthorizationService authorizationService | ||
) | ||
public override IDisplayResult Edit(ElasticSettings settings) | ||
=> Initialize<ElasticSettingsViewModel>("ElasticSettings_Edit", async model => | ||
{ | ||
_elasticIndexSettingsService = elasticIndexSettingsService; | ||
_httpContextAccessor = httpContextAccessor; | ||
_authorizationService = authorizationService; | ||
model.SearchIndex = settings.SearchIndex; | ||
model.SearchFields = string.Join(", ", settings.DefaultSearchFields ?? []); | ||
model.SearchIndexes = (await _elasticIndexSettingsService.GetSettingsAsync()).Select(x => x.IndexName); | ||
model.DefaultQuery = settings.DefaultQuery; | ||
model.SearchType = settings.GetSearchType(); | ||
model.SearchTypes = [ | ||
new(S["Multi-Match Query (Default)"], string.Empty), | ||
new(S["Query String Query"], ElasticSettings.QueryStringSearchType), | ||
new(S["Custom Query"], ElasticSettings.CustomSearchType), | ||
]; | ||
}).Location("Content:2") | ||
.RenderWhen(() => _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, Permissions.ManageElasticIndexes)) | ||
.OnGroup(GroupId); | ||
|
||
public override async Task<IDisplayResult> UpdateAsync(ElasticSettings section, BuildEditorContext context) | ||
{ | ||
if (!string.Equals(GroupId, context.GroupId, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return null; | ||
} | ||
|
||
public override async Task<IDisplayResult> EditAsync(ElasticSettings settings, BuildEditorContext context) | ||
if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext?.User, Permissions.ManageElasticIndexes)) | ||
{ | ||
var user = _httpContextAccessor.HttpContext?.User; | ||
return null; | ||
} | ||
|
||
if (!await _authorizationService.AuthorizeAsync(user, Permissions.ManageElasticIndexes)) | ||
{ | ||
return null; | ||
} | ||
var model = new ElasticSettingsViewModel(); | ||
|
||
return Initialize<ElasticSettingsViewModel>("ElasticSettings_Edit", async model => | ||
{ | ||
model.SearchIndex = settings.SearchIndex; | ||
model.SearchFields = string.Join(", ", settings.DefaultSearchFields ?? Array.Empty<string>()); | ||
model.SearchIndexes = (await _elasticIndexSettingsService.GetSettingsAsync()).Select(x => x.IndexName); | ||
model.AllowElasticQueryStringQueryInSearch = settings.AllowElasticQueryStringQueryInSearch; | ||
}).Location("Content:2").OnGroup(GroupId); | ||
} | ||
await context.Updater.TryUpdateModelAsync(model, Prefix); | ||
|
||
public override async Task<IDisplayResult> UpdateAsync(ElasticSettings section, BuildEditorContext context) | ||
{ | ||
var user = _httpContextAccessor.HttpContext?.User; | ||
section.DefaultQuery = null; | ||
section.SearchIndex = model.SearchIndex; | ||
section.DefaultSearchFields = model.SearchFields?.Split(_separator, StringSplitOptions.RemoveEmptyEntries); | ||
section.SearchType = model.SearchType ?? string.Empty; | ||
|
||
if (!await _authorizationService.AuthorizeAsync(user, Permissions.ManageElasticIndexes)) | ||
if (model.SearchType == ElasticSettings.CustomSearchType) | ||
{ | ||
if (string.IsNullOrWhiteSpace(model.DefaultQuery)) | ||
{ | ||
return null; | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.DefaultQuery), S["Please provide the default query."]); | ||
} | ||
|
||
if (context.GroupId.Equals(GroupId, StringComparison.OrdinalIgnoreCase)) | ||
else if (!JsonHelpers.TryParse(model.DefaultQuery, out var document)) | ||
{ | ||
var model = new ElasticSettingsViewModel(); | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.DefaultQuery), S["The provided query is not formatted correctly."]); | ||
} | ||
else | ||
{ | ||
section.DefaultQuery = JsonSerializer.Serialize(document, _jsonSerializerOptions); | ||
|
||
await context.Updater.TryUpdateModelAsync(model, Prefix); | ||
try | ||
{ | ||
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(model.DefaultQuery)); | ||
|
||
section.SearchIndex = model.SearchIndex; | ||
section.DefaultSearchFields = model.SearchFields?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); | ||
section.AllowElasticQueryStringQueryInSearch = model.AllowElasticQueryStringQueryInSearch; | ||
var searchRequest = await _elasticClient.RequestResponseSerializer.DeserializeAsync<SearchRequest>(stream); | ||
} | ||
catch | ||
{ | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.DefaultQuery), S["Invalid query provided."]); | ||
} | ||
} | ||
|
||
return await EditAsync(section, context); | ||
} | ||
|
||
return await EditAsync(section, context); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 12 additions & 1 deletion
13
...chardCore.Modules/OrchardCore.Search.Elasticsearch/ViewModels/ElasticSettingsViewModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,24 @@ | ||
using System.Collections.Generic; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
using Microsoft.AspNetCore.Mvc.Rendering; | ||
|
||
namespace OrchardCore.Search.Elasticsearch.ViewModels | ||
{ | ||
public class ElasticSettingsViewModel | ||
{ | ||
public string Analyzer { get; set; } | ||
|
||
public string SearchIndex { get; set; } | ||
|
||
public IEnumerable<string> SearchIndexes { get; set; } | ||
|
||
public string SearchFields { get; set; } | ||
public bool AllowElasticQueryStringQueryInSearch { get; set; } | ||
|
||
public string DefaultQuery { get; set; } | ||
|
||
public string SearchType { get; set; } | ||
|
||
[BindNever] | ||
public IEnumerable<SelectListItem> SearchTypes { get; set; } | ||
} | ||
} |
Oops, something went wrong.