chris48s / cakephp-geodistance

:cake: A CakePHP 3 geodistance model behavior :earth_africa:
https://packagist.org/packages/chris48s/cakephp-geodistance
MIT License
5 stars 1 forks source link

Alias and Autofields #1

Closed dcodadigital closed 8 years ago

dcodadigital commented 8 years ago

Avoids ambiguous field names if "latitude" or "longitude" are the set field column names.

Included autoFields so that the select fields are not over written if combined with another query.

chris48s commented 8 years ago

Hi @dcodadigital.

Your bug report is completely valid, so thanks for submitting it. I see what you are getting at with your attempted solution, but there are some problems with your patch. I can see from your profile that you are fairly new to this, so I'll run you through it.

$this->_config['latitudeColumn'] = $this->_table->alias() . '.' . $this->_config['latitudeColumn'];
$this->_config['longitudeColumn'] = $this->_table->alias() . '.' . $this->_config['longitudeColumn'];

This is a more generic solution.

Hints:

vendor/bin/phpunit

and check against coding standards with

vendor/bin/phpcs -n -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP --ignore=vendor --ignore=docs --ignore=tests/bootstrap.php .

I'd like to include your patch, rather than just fixing the bug myself, so I look forward to receiving an updated PR from you.

dcodadigital commented 8 years ago

Hey @chris48s

Thanks for spending time to reply in such depth with some very quality pointers I'll certainly take on-board going forward.

That's a good point on the if statements they can just be aliased without them. I had to look at the query as I found out the aliases would not work within the query conditions as they were so ended up changing that slightly: -

$query->autoFields(true)->find('all')
->select(['distance' => $distance])
->bind(':earth_radius', $earthRadius, 'integer')
->bind(':latitude', $latitude, 'float')
->bind(':longitude', $longitude, 'float')->where([$distance . "<=" . $radius]);

I will have another go and submit another PR over this weekend and use proper unit testing. Thanks for your patience with me.

chris48s commented 8 years ago

OK, so you've figured out how to make it work, but I think your solution now introduces that SQL Injection flaw I talked about. $radius could be user supplied data, so we need to ensure it is sanitized before sending it to the database. There's probably several ways to deal with that, but for consistency with the rest of the code, I'd make a named parameter :radius, so we can rewrite that as:

$queryOptions = [
    'fields' => ['distance' => $distance],
    'order' => ['distance ASC'],
    'conditions' => ["$distance <= :radius"]
];
$query->find('all', $queryOptions)
->autoFields(true)
->bind(':earth_radius', $earthRadius, 'integer')
->bind(':latitude', $latitude, 'float')
->bind(':longitude', $longitude, 'float')
->bind(':radius', $radius, 'float');

You should now have what you need to submit a working (secure) patch.

I actually think CakePHP needs to be more explicit about the cases where it doesn't sanitize input as I think the docs don't make it clear enough that

'conditions' => ["$distance <=" => $radius]

is safe, but

'conditions' => ["$distance <= $radius"]

is not!

chris48s commented 8 years ago

Fixed in ab3c631 - closing