HQL Injection/findAll with sorting - grails

In my application, the query is being built by appending the first part(where clause) with the second part(order by) using a separate script like QueryBuilder.groovy and hence the order by part is prone to HQL injection which can't be sanitized by using Named Parameters. Therefore, I want to use findAll to retrieve a set of records by passing it a query and sorting and paging parameters separately. I saw an implementation like this:
domainClass.findAll(query,[namedParams],[max: 10, offset: 5])
When i passed sortColumn and sortDirection as named parameters, sortColumn worked fine but sortDirection didn't work. i need a way to either make sortDirection work as a named parameter or any other way which will combine 'sorting by direction' with the findAll result. Many people have suggested on various forums to just use the parameters directly as part of the query but it is unacceptable for my application as it will expose the query to HQL Injection.
Thanks in advance.
here is an example:
queryString = "FROM BookCatalog b WHERE b.bookNumber = :bookNumber"
this is passed to the QueryBuilder.groovy where something like this happens:
sort = "$params.sortColumn $params.sortDirection"
queryString.order(sort)
public void sort(String query){
this.query = this.query+" order by "+query
}
finally findAll retrieves the list of records:
def list = findAll(queryString,namedParams,queryParams)
so as the logic just appends the sorting parameters to the query string a potential hacker can do something like this:
bookCatalogView?offset=2&max=5&sortColumn=1,2,3 **or 1=1**
or
bookCatalogView?offset=2&max=5&sortColumn=1,2,3;**select * from whatever**

Don't concat strings, it's bad practice.
If you want to create complex queries, consider using createCriteria()
SomeDomainClass.createCriteria().list {
order("propName", "desc")
}
or, if you need more control, in the sessionFactory way:
query = sessionFactory.getCurrentSession().createCriteria(DomainClass.class)
query.addOrder(Order.asc("someField"))
query.addOrder(Order.desc("someotherField"))

Related

How to query on calculated column using Breeze

I have two columns in my database table (dueDate & lateMinutes).
How do I create a Where predicate that adds lateMinutes to dueDate and compares the result to a given date (aGivenDate).
eg. .where(dueDate + lateMinutes > aGivenDate)
Any idea how to do this with a Breeze query where predicate?
Any help appreciated.
Regards,
Paul.
There is no standard query syntax supporting date arithmetic within breeze, so your best bet for this would be to use a named query with a parameter. i.e. So assuming that the name of your EntityType was say 'Schedule' something like this
On the client
var q = EntityQuery.from("SchedulesAfter")
.where(...) // this can be any valid where clause for the 'Schedule' type ( or can be omitted completely if you don't need additional query restrictions.
.withParameter( { givenDate: aGivenDate });
On the server
[HttpGet]
public IQueryable<Schedule> SchedulesAfter(DateTime givenDate) {
// This needs to return a valid IQueryable
// You will need to find the correct EF syntax to support your query here. You may need to use an EF function here instead.
return ContextProvider.Context.Schedules
.Where(s => DbFunctions.AddMinutes(s.DueDate ,s.LateMinutes) > givenDate);
}
In effect, you are calling a custom query method on the server with a parameter and then telling the server how to implement the query using this parameter.

How to optimize the select attributes in Grails?

I have an application in production use, when a user goes to a proposal index page it takes a very long time and sometimes times out. I've narrowed down the issue to be a SQL statement that is selecting all the Proposal objects. The problem is the Proposal object has many images (byte[]) stored in memory that aren't being used in the index page. These images are huge thus causing the problem.
What are the different ways I can optimize this query in Grails to remove the attributes I don't need on that page or only add the attributes I have in my GSP?
Here is the controller code (scaffolded):
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Proposal.list(params), model:[proposalInstanceCount: Proposal.count()]
}
Thanks!
I wrote a plugin for this scenario, see http://grails.org/plugin/lazylob
Another option is to refactor the domain class into two. Put the image data in the new domain class:
class ProposalImage {
byte[] image
}
and reference it from the Proposal class:
class Proposal {
ProposalImage proposalImage
// other properties
}
Since references are lazy by default, GORM will only load the image data from the new domain class if you specifically refer to it.
EDIT (updated with subselect approaches):
You can also use custom queries to select a subset of the properties. Probably the most convenient would be using "select new map" in an HQL query:
def results = Proposal.executeQuery(
'select new map(prop1 as prop1, prop2 as prop2) from Proposal',
[max:params.max as int, params.offset as int])
This is convenient because each element in the results list is a map keyed with the property names, so it will look the same as a real Proposal instance in the GSP.
Another option if you prefer criteria queries is to use projections to limit which properties are returned:
def results = Proposal.withCriteria {
projections {
property 'prop1'
property 'prop2'
}
maxResults(params.max as int)
firstResult(params.offset as int)
}
Each item in the results is an Object[] array and each element in the array is the actual type of the property. You would need to manually build a list of maps, e.g.
results = results.collect { result -> [prop1: result[0], prop2: result[1]] }
Additionally, you can automate this by finding all of the names of the persistent properties and excluding the one (or ones) you want to avoid: def propNames = grailsApplication.getDomainClass(Proposal.name).persistentProperties*.name

BreezeJS - Regular expression in Where Clause

I'm trying to do something like:
var predicate = breeze.Predicate.create('columnName', breeze.FilterQueryOp.Contains, 'regexHere');
manager.executeQuery(entityQuery.From('tableName').where(predicate));
It all works fine when I try to search it "normal" way, but I'd like to include regex search that would work as sql LIKE operator. Mostly, I'm interested in how to make clause similar to sqls:
WHERE columnName LIKE '%abc%def%'
Is that possible with Breeze?
Sorry but [FilterQueryOp.Contains], FilterQueryOp.StartsWith and FilterQueryOp.EndsWith are the closest query operators to what you want. The OData spec that is used to construct a query url does not support regex based queries.
That said you can use EntityQuery.withParameters to do whatever you want with any parameters passed from a client. For example
// Client side
var query = EntityQuery.from("CustomersByRegex")
.withParameters({ regex: myRegex });
// Server side
[HttpGet]
public IQueryable<Customer> CustomersByRegex(string regex) {
// use the regex here against your customers collection
// and return the resulting customers;
}
You can also mix and match the two mechanisms. i.e. a regular breeze query with Filters and a 'withParamters' call.

findBy multiple attributes (findAllWhere)

I have an object from which I must filter certain attributes, some of which could also be "null". I have a Filter object and a Product object.
In the Filter object I have certain attributes reflecting the Product object which can be filled out or be left blank. Here a shortened view on the classes.
Product: String name, Boolean isEmpty, ...., belongsTo [Producer, Distributor]...
Filter: Boolean isEmpty, ... belongsTo [Producer, Distributor]...
With this filter I can search for all Products having certain attributes (empty, Producer, Distributor).
I have an export functionality where I can select the filter and it outputs the information based on that selection for the Products.
As all of these attributes can be null, but also contain a value, I first of thought to construct an own search query (combining strings etc) to construct an SQL-string and then using Product.findAll(string_query, string_params). But as this is quite tedious, I changed it now to someting like this:
if(filter.producer)
prods = Product.findAllWhere(producer:filter.producer)
if(filter.distributor)
prods = prods.findAll {it.distributor == filter.distributor}
if(filter.isEmpty!=null) //as it could be NULL but also false/true
prods = prods.findAll {it.isEmpty == filter.isEmpty}
But this becomes quite a larger task if I have 10-15 attributes to be filtered. I'm not very experienced with Grails or Groovy but I guess this can be solved easier, right?
I believe you'll find Grails Criteria queries to be a very nice way to accomplish tasks like this. See:
http://grails.org/doc/latest/guide/single.html#criteria
http://viaboxxsystems.de/the-grails-hibernatecriteriabuilder
Your sample might look something like this when expressed as a criteria query:
def prods = Product.createCriteria().list {
if(filter.producer) eq("producer", filter.producer)
if(filter.distributor) eq("distributor", filter.distributor)
if(filter.isEmpty != null) eq("isEmpty", filter.isEmpty)
}

Multiple search criteria in a repository

I have a question for how to implement multiple criteria for a repository pattern in ASP.net MVC. Imagine a POCO class in EF4
public class people
{ String Name {get;set;}
float Height {get;set;}
float Weight {get;set;}
int age {get;set;}
....
}
If I build up a repository as IPeopleRepository, what kind of methods should I implement for a multiple criteria search (e.g Age > 30, Height >80). Those criteria would be related to the properties in the class and some of the input could be null. Of course I can write a method like
People SearchPeople (int age, float height.....)
but I have to judge if every variable would be null and append onto the search queries..
So do you have any good ideas on how to implement this function in EF?
It sounds like your looking for something like the Specification pattern.
There is a great article involving EF4 / POCO / Repository / Specification pattern here.
Although i like the pattern, i find it a bit overkill in simple scenarios.
I ended up using the "pipes and filters" technique - basically IQueryable<T> extension methods on your objects to make your repository code fluent.
For a search criteria however, i would be tempted to allow the consuming code to supply the predicate, then you don't have to worry about the parameters.
So the definition would be like this:
public People SearchPeople(Expression<Func<People,bool>> predicate)
{
return _context.People.SingleOrDefault(predicate);
}
Then the code simply supplies the predicate.
var person = _repository.SearchPeople(p => p.Age > 30 && p.Height > 80);
Some people don't like this technique, as it gives too much "power" to the consumer, because they might supply a predicate like p.Id > 0 and return all the rows in the database.
To counteract that, provide an optional parameter for maxRows. If it's not supplied, default to 100 rows.
First, you need to think if you really need repository search method.
You might want to do direct queries instead of wrapping them to repository.
However, if you think you need the search method than you will likely use something like this:
private People SearchPeople(int? age, float? height)
{
var baseQuery = db.People;
if (age != null)
baseQuery = baseQuery.Where(arg => arg.Age > age);
if (height != null)
baseQuery = baseQuery.Where(arg => arg.Height > height);
return baseQuery.ToList();
}
Although you didn't want to do this, I can't think of better solution.
Basically I think there are three options:
Use Specification pattern and create as many single specification as you need then you can more complex specification by combining them via And/Or/Not operators. You can look at here for an example http://code.google.com/p/linq-specifications/
Create a search method that accept an input predicate, it's most simple one since it leaves all criteria filtering works to consumers.
Create a search method with different criteria, then build dynamic Linq expression. There is a PredicateBuilder here: http://www.linqpad.net (look for LinqKit project).

Resources