WebApi
WebApi copied to clipboard
Filter on a property is being allowed, even though attribute is set as not filterable using Filter Attribute [Filter(Disabled = true)]
Filter on a property is being allowed, even though attribute is set as not filterable using Filter Attribute [Filter(Disabled = true)]
Assemblies affected
Microsoft.AspNetCore.OData 7.4.0
Reproduce steps
Define a property as filterable false as shown below
public class CosmosBaseEntity : IBaseEntity
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
[JsonProperty("id")]
[ExcludeFromResponse]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "for Cosmos")]
public string id { get; set; }
/// <summary>
/// Gets or sets the type of the entity.
/// </summary>
[ExcludeFromResponse]
public string EntityType { get; set; }
/// <summary>
/// Gets or sets the type of the partition key of Document.
/// </summary>
[ExcludeFromResponse]
public string PartitionKey { get; set; }
/// <summary>
/// Gets or sets the action.
/// </summary>
[ExcludeFromResponse]
public string Action { get; set; }
/// <summary>
/// Gets or sets a value indicating whether deleted.
/// </summary>
/// <value>
/// <c>true</c> if this instance is deleted; otherwise, <c>false</c>.
/// </value>
[ExcludeFromResponse]
public bool? IsDeleted { get; set; }
/// <summary>
/// Gets or sets CreatedBy.
/// </summary>
[Filter(Disabled = true)]
public string CreatedBy { get; set; }
/// <summary>
/// Gets or sets SourceCreatedOn.
/// </summary>
public DateTime CreatedOn { get; set; }
/// <summary>
/// Gets or sets ModifiedBy.
/// </summary>
public string ModifiedBy { get; set; }
/// <summary>
/// Gets or sets ModifiedOn.
/// </summary>
public DateTime ModifiedOn { get; set; }
/// <summary>
/// Gets or sets the e tag.
/// </summary>
[JsonProperty(PropertyName= "_etag")]
[ExcludeFromResponse]
public string ETag { get; set; }
}
public class Candidate : CosmosBaseEntity
{
/// <summary>
/// Gets or sets CandidateId.
/// </summary>
[Key]
public int CandidateId { get; set; }
/// <summary>
/// Gets or sets the first name of the candidate.
/// </summary>
/// <value>
/// The first name of the candidate.
/// </value>
public string CandidateFirstName { get; set; }
/// <summary>
/// Gets or sets the last name of the candidate.
/// </summary>
/// <value>
/// The last name of the candidate.
/// </value>
public string CandidateLastName { get; set; }
/// <summary>
/// Gets or sets the name of the candidate middle.
/// </summary>
/// <value>
/// The name of the candidate middle.
/// </value>
public string CandidateMiddleName { get; set; }
/// <summary>
/// Gets or sets the first name of the candidate preferred.
/// </summary>
/// <value>
/// The first name of the candidate preferred.
/// </value>
public string CandidatePreferredFirstName { get; set; }
}
And in the controller
validate the filters as below
[HttpGet]
[ODataRoute]
[Authorize]
[EnableQuery(PageSize = 100)]
public ActionResult<IQueryable<Candidate>> Get(ODataQueryOptions<Candidate> options)
{
var traceProps = new Dictionary<string, string>();
traceProps[Constants.Filter] = options.Filter?.RawValue;
this.logger.TraceInformation("In OData Candidate", traceProps);
options.Filter?.Validate(new ODataValidationSettings { });
var candidates = this.Cosmos.GetAllByEntityType<Candidate>(Constants.Candidate);
return this.Ok(candidates);
}
Expected result
If filter applied on the attributes which are set to disabled. It should not allow
Actual result
Filtering is allowed
Additional detail
*Its a simple repro, have a Filter attribute on any property. In Odata filter use that https://localhost:44371/odata/candidate?$filter=createdBy eq 'MICROSOFT' *
@reddaiahnethi I looked at this issue while investigating #2203. What I found is that if you applied FilterAttribute
at the class level and supply the list of properties that the rule applies to, it works, e.g.
[Filter("Property1", "InheritedProperty1", "etc", Disabled = true)]
public class Candidate
{
// ...
}
We'll need to figure out why it's ignored when applied to the property directly, unless it's not intended to work that way - https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnet.odata.query.filterattribute?view=odata-aspnetcore-7.0 cc. @Sreejithpin
@gathogojr I tried setting allowing filtering and it didn't work either on the property level, for the latest version of OData (but at class level it worked).
In case it doesn't work at property level and only works at class level, it would be easier if the attribute had at the top (to disallow misusage): [AttributeUsage(AttributeTargets.Class)]