CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • Google Summer of Code »
  • Params from url to sql, the secure way
Pages: [1]

Author Topic: Params from url to sql, the secure way  (Read 1874 times)

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Params from url to sql, the secure way
June 16, 2014, 11:36:20 pm
Hi,

For the dataviz, we need to be able to set additional params for each dataviz (eg. the id of an event, a date range...)

So far, we have managed to avoid having to write any php (everything is in smarty or sql files), and I'm tempted to explore if we can keep it that way.

What do you think for the sql param:
queries/whatever.sql contains SELECT ... where contact_id=%1 and title=%2
and you can use it from your tpl:
Code: [Select]
<script>
var data={crmSQL file="whatever.sql" integer_1=2 string_2="bla"}

So any param looking like type_number is a sql param (to be passed to CRM_Core_DAO::executeQuery with the right type)

and for the http params, add a new {crmRequest name="paramA" type="string" method="GET"} that would retrieve ?paramA=bla and assign it to {$paramA}

so if you need to filter based on the event type, you call civicrm/dataviz/events?type=meeting

in your events.tpl you put

Code: [Select]
{crmRequest name="type" type="string"}
<script>
var data={crmSQL file=events.sql string_1=$type}


and query/events.sql
Code: [Select]
select bla from civicrm_events where event_type=%1
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Params from url to sql, the secure way
June 17, 2014, 12:52:57 am
So the advantage of this approach as opposed to say making the api optionally return sql rather than a result array is that the FROM clauses etc would be more complex than a standard event.get?

The advantage of making it an extension of api.get would be that when we add ACLs to the api we would kill 2 birds with a massive big rock
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Params from url to sql, the secure way
June 17, 2014, 01:06:20 am
the sql queries themselves are not "simple" select from but usually fetch aggregated data, so select count(*) group by ...

it could be solved by creating custom apis, but then means having to create more php code to provide extra services that aren't needed (we only want to fetch from the smarty template)
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Params from url to sql, the secure way
June 17, 2014, 01:08:23 am
Do you want to paste some examples?
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

s0014

  • I post occasionally
  • **
  • Posts: 56
  • Karma: 2
  • CiviCRM version: 4.4.5
  • CMS version: Drupal 7.28
  • MySQL version: 5.5.37
  • PHP version: 5.5.9
Re: Params from url to sql, the secure way
June 17, 2014, 12:11:44 pm
Hey Eileen,

What we are trying to do here is create a method which can pull aggregated custom data. For instance, I need to get the information for a particular events and details of its all the participants. That will basically help me to show a demographic viz of how the event participants look like. When do they register etc etc.

Currently our function excepts a SQL query with no parameters. Now to pull details of a particular event and its participants, we need to get details with event.id is something. Where we are confused is, is there an secure way to do it? because this id is fed by the user in the url he can actually go ahead with putting harmful parameters keeping in mind that we need as less php as possible.



Sid
DataViz Project, GSoC 2014

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Params from url to sql, the secure way
June 17, 2014, 12:24:31 pm
we don't "need" as little php as possible, but so far, I like the idea of having to put a single template at the right place and get it working.

example of query:

https://github.com/TechToThePeople/civisualize/blob/master/queries/contacts.sql

For that one, we for instance would want to have a new contacts_in_group.sql that would only analyse the contacts belonging to a specific group.

Make sense?

X+
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Params from url to sql, the secure way
June 17, 2014, 04:11:26 pm
Really the group by is the only complex bit there isn't it?

 I would consider adding a new generic api function called getsql & having Group by as an option? (group by could be added as an option to get anyway - it wouldn't be of much value usually but it would be easy & safe to add in & would be in a central place.
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Params from url to sql, the secure way
June 17, 2014, 05:51:21 pm
For reporting, I tend to agree that SQL is easier to work with than custom API functions. The nice thing about the described {crmSQL} helper (or an analogous API) is that the remoter caller doesn't actually write the SQL: the SQL is always coded on the server-side in a file.

Other random comments...

1. I'd personally find it easier to read if the parameter position/type were swapped, eg "1_integer=123" instead of "integer_1=123". To my eye, "integer_1" looks like "integer #1", which makes me think "integer #1" and "string #1" are two totally different things (which could coexist).  But that's probably not the intention.

2. How should one handle file-lookup with multiple extensions? It seems like you'd need to know the name of the extension so that you can lookup SQL from the right folder. e.g.

Code: [Select]
{crmSQL ext="org.example.mymodule" file="my-query.sql"}

// ...or use the same approach {ts}...

{crmScope extensionKey="org.example.mymodule"}
  {crmSQL file="my-query.sql"}
{/crmScope}

3. This is probably wishful thinking, but it would make even more sense to me to use named parameters with types declared in the .sql file, e.g. one way might be https://gist.github.com/totten/d4206ca9a5cc715c66c0 (Note: That example makes two passes through the template -- once to get list of variables/types and once to evaluate SQL. There might be a simpler way, but I just wanted to get something readable.)

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Params from url to sql, the secure way
June 17, 2014, 11:15:33 pm

Quote from: Eileen on June 17, 2014, 04:11:26 pm
Really the group by is the only complex bit there isn't it?

 I would consider adding a new generic api function called getsql & having Group by as an option? (group by could be added as an option to get anyway - it wouldn't be of much value usually but it would be easy & safe to add in & would be in a central place.

I'm not too sure why, but my feeling is that we increase the attack surface (now everyone having an access to the api can much more easily try to sql/inject..) without additional benefits.

This being said, it would be trivial to add an api wrapper to provide an access to the sql queries later on if we realise we need it.

Quote
1. I'd personally find it easier to read if the parameter position/type were swapped, eg "1_integer=123" instead of "integer_1=123".

Seems clearer indeed.

Quote
2. How should one handle file-lookup with multiple extensions?
It seems like you'd need to know the name of the extension so that you can lookup SQL from the right folder

So far, I only needed template lookup with multiple extensions (and it works fine, but with the limitation that everything is under the same url namespace /civicrm/dataviz )

side node: May be we should reserve /civicrm/tld.domain.extension (two dots in the template name part of the url) as a way to uniquely identify the tpl you want so several extensions can offer a dashboard

We could offer the optional ext param and by default lookup for the sql in the same extension as the template file is.

Quote
3. This is probably wishful thinking, but it would make even more sense to me to use named parameters with types declared in the .sql file, e.g. one way might be https://gist.github.com/totten/d4206ca9a5cc715c66c0 (Note: That example makes two passes through the template -- once to get list of variables/types and once to evaluate SQL. There might be a simpler way, but I just wanted to get something readable.)

I might as well solve another problem I had: that the sql to run might be different depending if a param exists (eg. group by something empty isn't going to work)

I'll move the discussion about templating the sql in a new thread
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Params from url to sql, the secure way
June 18, 2014, 01:37:32 am
Quote from: xavier on June 17, 2014, 11:15:33 pm
I'm not too sure why, but my feeling is that we increase the attack surface (now everyone having an access to the api can much more easily try to sql/inject..) without additional benefits.

This being said, it would be trivial to add an api wrapper to provide an access to the sql queries later on if we realise we need it.

{crmSQL} seems to have two modes: it can accept raw SQL, or it can use a named SQL query (file). Raw SQL seems OK for server-side code but is a non-starter for remote APIs. The named SQL queries could be OK for an API (given suitable authorization logic). FWIW, I'd be less worried about injections stemming from user-supplied data with a REST call than with Smarty *.tpl files.

There's a general limitation with authorizations in both the current implementation of "/civicrm/dataviz" and (as I understand) the proposed APIs: in "/civicrm/dataviz", any user with permission "access CiviCRM" can request any dataviz .tpl, which means they can probably get the data for any named-query (assuming that the named-queries are actually used). If one did a simple API wrapper for the named-queries, then it would probably have the same limitation (eg anyone with "access CiviCRM" could get the query results). Not a problem for small orgs / simple installations, so maybe not a priority for you now, but could be an issue with bigger orgs. But maybe there's a simple solution -- like a adding a new Smarty function "{crmAuthorize perm='access CiviEvent'}" (which throws an exception if you lack permission).

Quote from: xavier on June 17, 2014, 11:15:33 pm
So far, I only needed template lookup with multiple extensions (and it works fine, but with the limitation that everything is under the same url namespace /civicrm/dataviz )

side node: May be we should reserve /civicrm/tld.domain.extension (two dots in the template name part of the url) as a way to uniquely identify the tpl you want so several extensions can offer a dashboard

We could offer the optional ext param and by default lookup for the sql in the same extension as the template file is.

Aah, I hadn't read the code. I understand now -- when {crmSQL} loads a file, it searches the include_path, and each extension adds itself to the include_path. So there's some risk of collision (where two extensions have the same query-file), but that's easily managed downstream (eg by giving files distinctive names).

Quote from: xavier on June 17, 2014, 11:15:33 pm
I'll move the discussion about templating the sql in a new thread

Will join you over there...

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Params from url to sql, the secure way
June 18, 2014, 04:49:47 am
Quote from: totten on June 18, 2014, 01:37:32 am
There's a general limitation with authorizations in both the current implementation of "/civicrm/dataviz" and (as I understand) the proposed APIs: in "/civicrm/dataviz", any user with permission "access CiviCRM" can request any dataviz
[...] there's a simple solution -- like a adding a new Smarty function "{crmAuthorize perm='access CiviEvent'}" (which throws an exception if you lack permission).

I like it and would have found it handy in some integration projects (eg. do a custom tpl for a members only event that shouldn't allow anonymous registration, even if some other events are open to everyone).

Should sid create an issue and PR it?
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Params from url to sql, the secure way
June 18, 2014, 01:53:26 pm
Yeah I can see the use case for crmAuthorize
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Pages: [1]
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • Google Summer of Code »
  • Params from url to sql, the secure way

This forum was archived on 2017-11-26.