-
Notifications
You must be signed in to change notification settings - Fork 569
PUT/DELETE spec defined search params not allowed #5266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,10 +4,13 @@ | ||||||||||||||||||||||||||||
| // ------------------------------------------------------------------------------------------------- | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| using System; | |||||||||||||||||||||||||||||
| using System.Linq; | |||||||||||||||||||||||||||||
| using System.Threading; | |||||||||||||||||||||||||||||
| using System.Threading.Tasks; | |||||||||||||||||||||||||||||
| using EnsureThat; | |||||||||||||||||||||||||||||
| using MediatR; | |||||||||||||||||||||||||||||
| using Microsoft.Health.Fhir.Core.Exceptions; | |||||||||||||||||||||||||||||
| using Microsoft.Health.Fhir.Core.Features.Definition; | |||||||||||||||||||||||||||||
| using Microsoft.Health.Fhir.Core.Features.Persistence; | |||||||||||||||||||||||||||||
| using Microsoft.Health.Fhir.Core.Messages.Delete; | |||||||||||||||||||||||||||||
| using Microsoft.Health.Fhir.Core.Models; | |||||||||||||||||||||||||||||
|
|
@@ -17,33 +20,63 @@ namespace Microsoft.Health.Fhir.Core.Features.Search.Parameters | ||||||||||||||||||||||||||||
| public class DeleteSearchParameterBehavior<TDeleteResourceRequest, TDeleteResourceResponse> : IPipelineBehavior<TDeleteResourceRequest, TDeleteResourceResponse> | |||||||||||||||||||||||||||||
| where TDeleteResourceRequest : DeleteResourceRequest, IRequest<TDeleteResourceResponse> | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| private ISearchParameterOperations _searchParameterOperations; | |||||||||||||||||||||||||||||
| private IFhirDataStore _fhirDataStore; | |||||||||||||||||||||||||||||
| private readonly ISearchParameterOperations _searchParameterOperations; | |||||||||||||||||||||||||||||
| private readonly IFhirDataStore _fhirDataStore; | |||||||||||||||||||||||||||||
| private readonly ISearchParameterDefinitionManager _searchParameterDefinitionManager; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| public DeleteSearchParameterBehavior(ISearchParameterOperations searchParameterOperations, IFhirDataStore fhirDataStore) | |||||||||||||||||||||||||||||
| public DeleteSearchParameterBehavior( | |||||||||||||||||||||||||||||
| ISearchParameterOperations searchParameterOperations, | |||||||||||||||||||||||||||||
| IFhirDataStore fhirDataStore, | |||||||||||||||||||||||||||||
| ISearchParameterDefinitionManager searchParameterDefinitionManager) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| EnsureArg.IsNotNull(searchParameterOperations, nameof(searchParameterOperations)); | |||||||||||||||||||||||||||||
| EnsureArg.IsNotNull(fhirDataStore, nameof(fhirDataStore)); | |||||||||||||||||||||||||||||
| EnsureArg.IsNotNull(searchParameterDefinitionManager, nameof(searchParameterDefinitionManager)); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| _searchParameterOperations = searchParameterOperations; | |||||||||||||||||||||||||||||
| _fhirDataStore = fhirDataStore; | |||||||||||||||||||||||||||||
| _searchParameterDefinitionManager = searchParameterDefinitionManager; | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| public async Task<TDeleteResourceResponse> Handle(TDeleteResourceRequest request, RequestHandlerDelegate<TDeleteResourceResponse> next, CancellationToken cancellationToken) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| var deleteRequest = request as DeleteResourceRequest; | |||||||||||||||||||||||||||||
| ResourceWrapper searchParamResource = null; | |||||||||||||||||||||||||||||
| ResourceWrapper customSearchParamResource = null; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| if (deleteRequest.ResourceKey.ResourceType.Equals(KnownResourceTypes.SearchParameter, StringComparison.Ordinal)) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| searchParamResource = await _fhirDataStore.GetAsync(deleteRequest.ResourceKey, cancellationToken); | |||||||||||||||||||||||||||||
| customSearchParamResource = await _fhirDataStore.GetAsync(deleteRequest.ResourceKey, cancellationToken); | |||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed, I am concerned with this approach as users could in theory create a param as "http://hl7.org/fhir/SearchParameter/" then perform a hard delete which removes from the table, but leaves it in PendingDelete and therefore it would have remained in def manager and not in resource table. To be more accurate, it might be better to use our JSON file that provides or Spec Defined parameters and if found in that file, we throw method not allowed.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will abandon this PR and create a new one with these changes. |
|||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // Check if this is a spec-defined SearchParameter (exists in definition manager but not in Resource table) | |||||||||||||||||||||||||||||
| if (customSearchParamResource == null) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| // Try to find by URL constructed from the resource ID | |||||||||||||||||||||||||||||
| // Spec-defined parameters typically have URLs like: http://hl7.org/fhir/SearchParameter/{id} | |||||||||||||||||||||||||||||
| var possibleUrl = $"http://hl7.org/fhir/SearchParameter/{deleteRequest.ResourceKey.Id}"; | |||||||||||||||||||||||||||||
| if (_searchParameterDefinitionManager.TryGetSearchParameter(possibleUrl, out var searchParameterInfo)) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| // Found in definition manager but not in Resource table - this is a spec-defined parameter | |||||||||||||||||||||||||||||
| throw new MethodNotAllowedException(string.Format(Core.Resources.SearchParameterDefinitionCannotDeleteSpecDefined, possibleUrl)); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // Also check all search parameters to see if any match this ID | |||||||||||||||||||||||||||||
| var matchingParam = _searchParameterDefinitionManager.AllSearchParameters | |||||||||||||||||||||||||||||
| .FirstOrDefault(sp => sp.Url.ToString().EndsWith($"/{deleteRequest.ResourceKey.Id}", StringComparison.OrdinalIgnoreCase)); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| if (matchingParam != null) | |||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| throw new MethodNotAllowedException(string.Format(Core.Resources.SearchParameterDefinitionCannotDeleteSpecDefined, matchingParam.Url)); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // Not found in Resource table or definition manager - doesn't exist | |||||||||||||||||||||||||||||
| throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundById, deleteRequest.ResourceKey.ResourceType, deleteRequest.ResourceKey.Id)); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| if (searchParamResource != null && searchParamResource.IsDeleted == false) | |||||||||||||||||||||||||||||
| if (customSearchParamResource != null && customSearchParamResource.IsDeleted == false) | |||||||||||||||||||||||||||||
Check noticeCode scanning / CodeQL Unnecessarily complex Boolean expression
The expression 'A == false' can be simplified to '!A'.
Copilot AutofixAI 4 days ago To fix the unnecessarily complex boolean expression, replace the comparison
Suggested changeset
1
src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
|||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||
| // First update the in-memory SearchParameterDefinitionManager, and remove the status metadata from the data store | |||||||||||||||||||||||||||||
| // then remove the SearchParameter resource from the data store | |||||||||||||||||||||||||||||
| await _searchParameterOperations.DeleteSearchParameterAsync(searchParamResource.RawResource, cancellationToken); | |||||||||||||||||||||||||||||
| // This is a custom search parameter | |||||||||||||||||||||||||||||
| await _searchParameterOperations.DeleteSearchParameterAsync(customSearchParamResource.RawResource, cancellationToken); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| return await next(cancellationToken); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.