// Pass ODataQueryOptions as parameter, and call validation manually public IHttpActionResult GetFromManager(ODataQueryOptions<Manager> queryOptions) { if (queryOptions.SelectExpand != null) { queryOptions.SelectExpand.LevelsMaxLiteralExpansionDepth = 5; } var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 }; try { queryOptions.Validate(validationSettings); } catch (ODataException e) { var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest); responseMessage.Content = new StringContent( string.Format("The query specified in the URI is not valid. {0}", e.Message)); return ResponseMessage(responseMessage); } var querySettings = new ODataQuerySettings(); var result = queryOptions.ApplyTo(_employees.OfType<Manager>().AsQueryable(), querySettings).AsQueryable(); return Ok(result, result.GetType()); }
public static ODataQueryOptions CreateValidQueryOptions(IEdmModel model, Type elementClrType, HttpRequestMessage request, ODataValidationSettings validationSettings) { var queryOptions = CreateQueryOptions(model, elementClrType, request); queryOptions.Validate(validationSettings); return queryOptions; }
// Disallow the 'desc' parameter for $orderby option. public override void Validate(OrderByQueryOption orderByOption, ODataValidationSettings validationSettings) { if (orderByOption.OrderByNodes.Any( node => node.Direction == OrderByDirection.Descending)) { throw new ODataException("The 'desc' option is not supported."); } base.Validate(orderByOption, validationSettings); }
public override void ValidateSingleValuePropertyAccessNode(SingleValuePropertyAccessNode propertyAccessNode, ODataValidationSettings settings) { // Validate if we are accessing some sensitive property of Order, such as Quantity if (propertyAccessNode.Property.Name == "Quantity") { throw new ODataException("Filter with Quantity is not allowed."); } base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings); }
public void AllowedOrderByProperties_Property_RoundTrips() { ODataValidationSettings settings = new ODataValidationSettings(); Assert.NotNull(settings.AllowedOrderByProperties); Assert.Equal(0, settings.AllowedOrderByProperties.Count); settings.AllowedOrderByProperties.Add("Id"); settings.AllowedOrderByProperties.Add("Name"); Assert.Equal(2, settings.AllowedOrderByProperties.Count); Assert.Equal("Id", settings.AllowedOrderByProperties[0]); Assert.Equal("Name", settings.AllowedOrderByProperties[1]); }
public void Ctor_Initializes_All_Properties() { // Arrange & Act ODataValidationSettings querySettings = new ODataValidationSettings(); // Assert Assert.Equal(AllowedArithmeticOperators.All, querySettings.AllowedArithmeticOperators); Assert.Equal(AllowedFunctions.AllFunctions, querySettings.AllowedFunctions); Assert.Equal(AllowedLogicalOperators.All, querySettings.AllowedLogicalOperators); Assert.Equal(0, querySettings.AllowedOrderByProperties.Count); Assert.Equal(AllowedQueryOptions.Supported, querySettings.AllowedQueryOptions); Assert.Equal(1, querySettings.MaxAnyAllExpressionDepth); Assert.Equal(100, querySettings.MaxNodeCount); Assert.Null(querySettings.MaxSkip); Assert.Null(querySettings.MaxTop); }
// Note this can be done through Queryable attribute as well public IQueryable<Order> Get(ODataQueryOptions queryOptions) { // Register a custom FilterByValidator to disallow custom logic in the filter query if (queryOptions.Filter != null) { queryOptions.Filter.Validator = new RestrictiveFilterByQueryValidator(); } // Validate the query, we only allow order by Id property and // we only allow maximum Top query value to be 9 ODataValidationSettings settings = new ODataValidationSettings() { MaxTop = 9 }; settings.AllowedOrderByProperties.Add("Id"); queryOptions.Validate(settings); // Apply the query return queryOptions.ApplyTo(OrderList.AsQueryable()) as IQueryable<Order>; }
public IHttpActionResult Get(ODataQueryOptions<DLManager> queryOptions) { ODataValidationSettings settings = new ODataValidationSettings(); settings.MaxExpansionDepth = 1; try { queryOptions.Validate(settings); } catch (ODataException e) { var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest); responseMessage.Content = new StringContent( String.Format("The query specified in the URI is not valid. {0}", e.Message)); return ResponseMessage(responseMessage); } var managers = queryOptions.ApplyTo(_DLManagers.AsQueryable()).AsQueryable(); return Ok(managers, managers.GetType()); }
/// <inheritdoc /> public override void Validate(ODataQueryOptions options, ODataValidationSettings validationSettings) { base.Validate(options, validationSettings); if (options.SelectExpand == null) { // Nothing to validate. return; } // We only validate the $expand operator, so a different mechanism is required to restrict access to a // navigation source directly. For example, we restrict $expand=Orders, but we don't restrict accessing // orders through /Orders. The recommendation for restricting access to a navigation source in the URL path // is to use an IAuthorizationFilter. SelectExpandClause selectExpandClause = options.SelectExpand.SelectExpandClause; IList<ExpandedNavigationSelectItem> expandedItems = GetExpandedProperties(selectExpandClause); foreach (ExpandedNavigationSelectItem item in expandedItems) { ValidateExpandedItem(item); } }
public void CanTurnOffAllValidation() { // Arrange HttpRequestMessage message = new HttpRequestMessage( HttpMethod.Get, new Uri("http://localhost/?$filter=Name eq 'abc'") ); ODataQueryContext context = ValidationTestHelper.CreateCustomerContext(); ODataQueryOptions option = new ODataQueryOptions(context, message); ODataValidationSettings settings = new ODataValidationSettings() { AllowedQueryOptions = AllowedQueryOptions.OrderBy }; // Act & Assert Assert.Throws<ODataException>(() => option.Validate(settings), "Query option 'Filter' is not allowed. To allow it, set the 'AllowedQueryOptions' property on EnableQueryAttribute or QueryValidationSettings."); option.Validator = null; Assert.DoesNotThrow(() => option.Validate(settings)); }
public void Validate_ThrowsValidationErrors_ForOrderBy() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType().GetEdmModel(); var message = new HttpRequestMessage( HttpMethod.Get, new Uri("http://server/service/Customers?$orderby=CustomerId,Name") ); var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(Customer)), message); ODataValidationSettings validationSettings = new ODataValidationSettings { MaxOrderByNodeCount = 1 }; // Act & Assert Assert.Throws<ODataException>(() => options.Validate(validationSettings), "The number of clauses in $orderby query option exceeded the maximum number allowed. The maximum number of $orderby clauses allowed is 1."); }
public void VerifyValidateOptions(ODataValidationSettings settings, string query, bool success) { var response = this.Client.PostAsync( this.BaseAddress + "/api/ValidatorTests/ValidateOptions?" + query, new ObjectContent<ODataValidationSettings>(settings, new JsonMediaTypeFormatter())).Result; if (success) { response.EnsureSuccessStatusCode(); } else { Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } }
public void CanTurnOffValidationForOrderBy() { // Arrange ODataQueryContext context = ValidationTestHelper.CreateCustomerContext(); OrderByQueryOption option = new OrderByQueryOption("Name", context); ODataValidationSettings settings = new ODataValidationSettings(); settings.AllowedOrderByProperties.Add("Id"); // Act & Assert Assert.Throws<ODataException>(() => option.Validate(settings), "Order by 'Name' is not allowed. To allow it, set the 'AllowedOrderByProperties' property on EnableQueryAttribute or QueryValidationSettings."); option.Validator = null; Assert.DoesNotThrow(() => option.Validate(settings)); }
public void CanTurnOffValidationForFilter() { ODataValidationSettings settings = new ODataValidationSettings() { AllowedFunctions = AllowedFunctions.AllDateTimeFunctions }; ODataQueryContext context = ValidationTestHelper.CreateCustomerContext(); FilterQueryOption option = new FilterQueryOption("substring(Name,8,1) eq '7'", context); Assert.Throws<ODataException>(() => option.Validate(settings), "Function 'substring' is not allowed. To allow it, set the 'AllowedFunctions' property on EnableQueryAttribute or QueryValidationSettings."); option.Validator = null; Assert.DoesNotThrow(() => option.Validate(settings)); }
public void CanTurnOffValidationForSkip() { // Arrange ODataValidationSettings settings = new ODataValidationSettings() { MaxSkip = 10 }; SkipQueryOption option = new SkipQueryOption("11", ValidationTestHelper.CreateCustomerContext()); // Act and Assert Assert.Throws<ODataException>(() => option.Validate(settings), "The limit of '10' for Skip query has been exceeded. The value from the incoming request is '11'."); option.Validator = null; Assert.DoesNotThrow(() => option.Validate(settings)); }
public IQueryable<ValidatorTests_Todo> ValidateWithCustomValidator(ODataQueryOptions options) { if (options.Filter != null) { options.Filter.Validator = new CustomFilterValidator(); } try { ODataValidationSettings settings = new ODataValidationSettings(); options.Validate(settings); } catch (ODataException ex) { throw new HttpResponseException(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex)); } return options.ApplyTo(todoes.AsQueryable()) as IQueryable<ValidatorTests_Todo>; }
public override void ValidateSingleValuePropertyAccessNode(Microsoft.OData.Core.UriParser.Semantic.SingleValuePropertyAccessNode propertyAccessNode, ODataValidationSettings settings) { if (propertyAccessNode.Property.Name == "ID") { visited = true; } base.ValidateSingleValuePropertyAccessNode(propertyAccessNode, settings); }
/// <summary> /// Validate the $select and $expand query based on the given <paramref name="validationSettings"/>. It throws an ODataException if validation failed. /// </summary> /// <param name="validationSettings">The <see cref="ODataValidationSettings"/> instance which contains all the validation settings.</param> public void Validate(ODataValidationSettings validationSettings) { if (validationSettings == null) { throw Error.ArgumentNull("validationSettings"); } if (Validator != null) { Validator.Validate(this, validationSettings); } }
public IHttpActionResult Get(ODataQueryOptions<LevelsEntity> queryOptions) { var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 5 }; try { queryOptions.Validate(validationSettings); } catch (ODataException e) { var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest); responseMessage.Content = new StringContent( Error.Format("The query specified in the URI is not valid. {0}", e.Message)); return ResponseMessage(responseMessage); } var querySettings = new ODataQuerySettings(); var result = queryOptions.ApplyTo(Entities.AsQueryable(), querySettings).AsQueryable(); return Ok(result, result.GetType()); }
public IHttpActionResult Get(int key, ODataQueryOptions<Employee> options) { if (options.SelectExpand != null) { options.SelectExpand.LevelsMaxLiteralExpansionDepth = 3; } var validationSettings = new ODataValidationSettings { MaxExpansionDepth = 3 }; try { options.Validate(validationSettings); } catch (ODataException e) { HttpResponseMessage resoponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, e.Message, e); return ResponseMessage(resoponse); } var querySettings = new ODataQuerySettings(); Employee employee = _employees.Single(e => e.ID == key); var result = options.ApplyTo(employee, new ODataQuerySettings()); Type type = result.GetType(); return Ok(result, type); }
public override void Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings) { base.Validate(filterQueryOption, settings); if (!visited) { throw new ODataException("$filter query must contain ID property"); } }
public IHttpActionResult Get(int key, ODataQueryOptions<DLEmployee> queryOptions) { ODataValidationSettings settings = new ODataValidationSettings(); settings.MaxExpansionDepth = 3; try { queryOptions.Validate(settings); } catch (ODataException e) { var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest); responseMessage.Content = new StringContent( String.Format("The query specified in the URI is not valid. {0}", e.Message)); return ResponseMessage(responseMessage); } var employee = _DLEmployees.Single(e=>e.ID == key); var appliedEmployee = queryOptions.ApplyTo(employee, new ODataQuerySettings()); return Ok(appliedEmployee, appliedEmployee.GetType()); }
/// <summary> /// Enables a controller action to support OData query parameters. /// </summary> public EnableQueryAttribute() { _validationSettings = new ODataValidationSettings(); _querySettings = new ODataQuerySettings(); }
public IHttpActionResult Get(ODataQueryOptions<DLEmployee> queryOptions) { if (queryOptions.SelectExpand != null) { queryOptions.SelectExpand.LevelsMaxLiteralExpansionDepth = 2; } ODataValidationSettings settings = new ODataValidationSettings(); settings.MaxExpansionDepth = 4; try { queryOptions.Validate(settings); } catch (ODataException e) { var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest); responseMessage.Content = new StringContent( String.Format("The query specified in the URI is not valid. {0}", e.Message)); return ResponseMessage(responseMessage); } var employees = queryOptions.ApplyTo(_DLEmployees.AsQueryable()).AsQueryable(); return Ok(employees, employees.GetType()); }
public IQueryable<Team> GetTeams(ODataQueryOptions queryOptions) { // Validate query options var settings = new ODataValidationSettings() { MaxTop = 400 }; queryOptions.Validate(settings); // Apply the filter before going through to check if links exist for significant performance improvements var teams = (IQueryable<Team>)queryOptions.ApplyTo(Db.core.Teams); // RouteLinker creates Uris for actions var linker = new RouteLinker(Request); foreach (var team in teams) { if (team.Links == null) { team.Links = new SerializableDynamic(); team.Links.url = linker.GetUri<TeamsController>(c => c.GetTeam(team.Number)).ToString(); } } var nextRequest = Request.RequestUri; return Db.core.Teams.AsQueryable(); }