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 »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • API/ Rest & Anonymous access
Pages: [1] 2

Author Topic: API/ Rest & Anonymous access  (Read 8131 times)

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
API/ Rest & Anonymous access
May 26, 2009, 08:08:37 pm
Hi all,

I would like to expose a certain result set to use for autocomplete in a registration form. I created a custom API (very basic) and can access it through this url

http://localhost/?q=civicrm/ajax/rest&fnName=civicrm/custom/search&json=1

Unfortunately I still can't get to it as anonymous user. I want to give this access. Is it possible to do so by adding a line specific to the url to civicrm_menu? Would that be an acceptable approach?

Eileen
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

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
May 27, 2009, 02:54:22 am
OK - I have looked into how this all works a little more. The issue of accessing 'public' data through REST was something we discussed briefly at Dev camp and it was agreed there was probably a place for it but there were other higher priority things. I guess this is a bit higher up my priority list.

Basically my requirement is that on registration there is a drop down list of companies with a particular custom field set. Either approach seems to require changes be made in the Core & I guess the second means I have to write them & convince someone to adopt them...

There are two main approaches I have been looking at to this

1) Wait until the core team deal with this http://issues.civicrm.org/jira/browse/CRM-4382 and attempt to back-port it. Assuming this isn't top on their priority list I'm focussing on:

2) Attempt to use the REST interface to provide the JSON for the autofill field. The problem I am hitting with this is permissions and the fact that the user is an anonymous user.

In theory people have agreed with me that where data is exposed through a search profile it is reasonable for it also to be accessible via a REST interface so I was looking to add an API function that would essentially return the same results as if you opened up a publicly viewable search page and entered them in. At the API level this is OK-ish but the problem is that anonymous users still can't access the REST function.

civicrm_menu defines that to access civicrm/ajax/rest you need access civicrm permission and if you have it you will call CRM_Utils_REST::ajax .

Under CRM_Utils_REST::ajax the comment is

        // this is driven by the menu system, so we can use permissioning to
        // restrict calls to this etc

by contrast to access

civicrm/profile it appears the main permissionning check is skipped and permissions are all managed by CRM_Core_Invoke::profile

The CRM_Core_Invoke::profile actually returns pretty much the correct data although there is a bit of bumf so it needs to be extracted into an array with only the right fields.

So, I guess I'm thinking the approach would need to be something like (NB I'm putting in specifics even when I think they may be wrong or it's just a guess because I think that people are more likely to correct me than to fill in the blanks.):

  • Create new path civicrm/ajax/rest/profile in civicrm_menu with access_callback=s:1:"1";
  • This new path could possibly still go through to the same function (CRM_Utils_REST::ajax) but add to that function a check so that the fnname is set to profile meaning that the only api that could be called that way would be the profile api.
  • Base the results created on the CRM_Core_Invoke::profile to ensure that permissionning is managed in the same way it would be for search profiles

NB I haven't thought deeply about the implications of what other functions might be hung off a profile api in the future or whether these possibilities would make the above a bad course of action.

Hope this makes sense....


« Last Edit: May 28, 2009, 01:00:12 am by Eileen »
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

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: API/ Rest & Anonymous access
May 27, 2009, 07:31:29 am

your plan makes sense :)

go for it. I would send the new path to a new function where u do the permission check before calling rest::ajax

lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
May 27, 2009, 11:53:04 am
OK - I'd like to see a response from Captain Morgan too to make sure it fits with his plans...
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

cap10morgan

  • I post occasionally
  • **
  • Posts: 56
  • Karma: 9
Re: API/ Rest & Anonymous access
May 27, 2009, 12:20:50 pm
I'm not totally clear on where and how this is hitting the API. That's the only part that where I would have some feedback. But this seems not to use the API (i.e. the code in api/v2/) nor the REST interface to it. That's OK, but it means I don't have much to add here.

Am I missing something? :)

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
May 27, 2009, 03:45:18 pm
The intent is to place the code in the api folder ie

api/v2/profile: - Function = Search to return REST available search results based on a profile.

So the call would be to http://loclhost/civicrm/ajax/rest/profile&fnname=civicrm/profile/search&gid=3&first_name=Wes

(gid = the profile & first_name would only work if it was defined in that profile)

The difference between this api call & others is that it would be available to anyone with the permission to 'access all profiles' rather than 'access civicrm' per the others. So if you display profiles to anonymous users they can also be queried using REST without logging in.




« Last Edit: May 28, 2009, 01:00:38 am by Eileen »
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

cap10morgan

  • I post occasionally
  • **
  • Posts: 56
  • Karma: 9
Re: API/ Rest & Anonymous access
May 27, 2009, 04:00:40 pm
I see. I haven't yet thought through how to integrate profiles into the API, and would probably want to consult with some others before we decided on a scheme.

So don't let me slow you down. Just do whatever works for now and then we'll figure out how to "do it right" later on (assuming it's even different, which it may not be).

But thanks for checking with me! :)

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
May 27, 2009, 06:05:05 pm
OK - I'll see how I go. Perhaps we can start some talk on this as well somewhere?

The key thing that needs to be considered for profiles from this conversation is that to allow them to use a different level of permissions the path needs to be different.
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

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
June 06, 2009, 04:43:42 am
OK - I've been working on this a bit further. I seem to have spent a lot of time figuring out what is going on and have only written a little sketchy code. It kind of works but it's not good enough. (I note the CiviCRM conventions on code commenting work on the assumption that the code speaks for itself)  I haven't been online much when people have been on IRC unfortunately so I'll post where I'm at and hopefully it will make sense

Have gotten to

http://localhost/classes2.2/?q=civicrm/ajax/rest/profile&fnName=civicrm/profile/search&json=1&gid=8

returns a JSON formatted array of the fields in the profile #8 and it is limited to the members of the group for which the profile applies.

Profiles which are not search enabled don't show up

I was surprised that on the main profile search functions

The profiles calls show up for anonymous users when they don't have 'profile listings and forms' permission. (This is v 2.2.3). I thought that that permission was used to limit access to search profiles.

I was also surprised to see individuals show in the search results for an organisation related profile

Problems

Basically I have tried to 'tread lightly' and use the existing functions - because I was trying to figure out how to make sure the code would survive upgrades and I was scared of missing out on important functions if I just picked those that I thought mattered. The functions I was focussed on were

   $selector =& new CRM_Profile_Selector_Listings( $fieldparams, $customFields, $gid );
   $rows = $selector->getRows( 8192,  $offset, $rowCount, $sort );

The problem I am having relates to the $sort field (it only works with no input if I change listings.php lines 383-387 from this


Code: [Select]
               $varArray[$key] = $field;
            }
        }
        $sort->_vars = $varArray;
       
       to this

Code: [Select]
               $varArray[$key] = $field;
            }
        $sort->_vars = $varArray;
        }
    
   




What I have done

I have added an extra line to the civicrm_menu as described (I guess it needs to be in the schema but haven't looked at that yet.)

Code: [Select]
INSERT INTO `civicrm_menu` (`id`, `path`, `path_arguments`, `title`, `access_callback`, `access_arguments`, `page_callback`, `page_arguments`, `breadcrumb`, `return_url`, `return_url_args`, `component_id`, `is_active`, `is_public`, `is_exposed`, `is_ssl`, `weight`, `type`, `page_type`, `skipBreadcrumb`) VALUES
(222, 'civicrm/ajax/rest/profile', NULL, NULL, 's:1:"1";', 'a:2:{i:0;a:1:{i:0;s:26:"profile listings and forms";}i:1;s:3:"and";}', 'a:2:{i:0;s:14:"CRM_Utils_REST";i:1;s:11:"ajaxProfile";}', NULL, 'a:1:{i:0;a:2:{s:5:"title";s:7:"CiviCRM";s:3:"url";s:43:"/classes2.2/index.php?q=civicrm&reset=1";}}', NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, 1, 1);


I have added a function to CRM_UTILS_Rest.php. This is exactly the same as the main ajax one except that it only allows the profile/search api to be accessed through this path.

Code: [Select]
   static function ajaxProfile(){
      //This is potentially available to anon users so is the same as ajax but with  fn restricted to profile/search
         $q = 'civicrm/profile/search';
         $args = explode( '/', $q );

        // If the function isn't in the civicrm namespace, reject the request.
        if ( $args[0] != 'civicrm' &&
             count( $args ) != 3 ) {
            return self::error( 'Unknown function invocation.' );
        }

        $result = self::process( $args, false );

        $config = CRM_Core_Config::singleton( );
        echo self::output( $config, $result );
        exit( );
    }


I have added the profile search function

Code: [Select]
*
 * @param  array   $params           (reference ) input parameters - not used
 *
 * @return array (reference )        array of contacts, if error an array with an error id and error message
 * @static void
 * @access public
 */
function &civicrm_profile_search( &$params ) {
    _civicrm_initialize( );


    $inputParams      = array( );
    $returnProperties = array( );
    $otherVars = array( 'sort', 'offset', 'rowCount', 'smartGroupCache' );
    
    $sort            = null;
    $offset          = 0;
    $rowCount        = 25;
    $smartGroupCache = false;
    foreach ( $params as $n => $v ) {
        if ( substr( $n, 0, 6 ) == 'return' ) {
            $returnProperties[ substr( $n, 7 ) ] = $v;
        } elseif ( in_array( $n, $otherVars ) ) {
            $$n = $v;
        } else {
            $inputParams[$n] = $v;
        }
    }

    if ( empty( $returnProperties ) ) {
        $returnProperties = null;
    }
    
   require_once 'CRM/Utils/Request.php';
           $gid = CRM_Utils_Request::retrieve('gid', 'Positive',
                                                  $this, true, 0, 'GET' );
        
        require_once 'CRM/Core/BAO/UFGroup.php';
        require_once 'CRM/Profile/Selector/Listings.php';
        require_once 'CRM/Profile/Page/Listings.php';

    
          $page =& new CRM_Profile_Page_Listings( );
          $returnArray=$page->preProcess( );
          $session =& CRM_Core_Session::singleton();
          $fieldparams =   $session->Get('profileParams' );
          
  
    
                  
        $customFields = CRM_Core_BAO_CustomField::getFieldsForImport( null );

        $selector =& new CRM_Profile_Selector_Listings( $fieldparams, $customFields, $gid );
                                                            
        $rows = $selector->getRows( 8192,  $offset, $rowCount, $sort );

 while (list($key,$value)=each ($rows))
{ $i = 0;
    foreach ($value as $key2=>$value2){
     
    if (isset($columnHeaders[$i]['sort'])){
      $fieldName = $columnHeaders[$i]['sort'];
      $newrows[$key][$fieldName]=$value2;
    }   $i++;
  }


        return $rows;
        

« Last Edit: June 09, 2009, 02:42:18 am by Eileen »
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: API/ Rest & Anonymous access
July 01, 2009, 07:52:36 am
Hi,

Not a big fan of providing unprotected access on an api. For instance in one case, I have the email of the contact part of the profile, but I then test on the template to see if the user is anonymous or not to decide to display it. Don't remember right now why I moved the access control in the template instead of doing it in the profile configuration, but it was a good reason.

Anyway, your profile api would make the data more widely open than I want.

What I would suggest it you duplicate the rest menu to openrest, leave it anonymous and modify the REST.php wrapper to allow only the one method (or two) you want, and override the return and other params, to add your groups criterias and whatelse

Makes 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: API/ Rest & Anonymous access
July 03, 2009, 02:35:14 pm
Hi there,

The problem with trying to add a path that enables anonymous access is that it is part of the schema and a bit of a pain to maintain as you can't put the xml files that get called on menu rebuild into the custom_php directory. It would be good to establish a path that could be used for this type of thing and would go in the schema.

Reading Xavier's e-mail an alternative suggestion is to add a path to the menu (e.g. civicrm/rest/anonymous) where people can put their own Api functions that they want anonymous users to have access to. Very little code would be required and people could use it or not as they wanted.

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

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: API/ Rest & Anonymous access
July 07, 2009, 09:16:50 pm
Hi Xavier,

I just thought I should note - what I was trying to do was make the SAME amount of information available to an anonymous user using the profile/search api call as would be available to an anonymous user using a search profile. If the anonymous user didn't have access to the data anyway, using a civicrm profile search, they shouldn't have it through the API.

What I was working to achieve was to implement any permissioning affecting the civicrm search profile and reflect it in the profile search api.
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: API/ Rest & Anonymous access
July 08, 2009, 04:06:11 am
Hi,

Still might be a potential risk. Some public field of the profile might not be displayed in the template. For instance, one of my public profile has an email but I decide in the template if I display it or not based on other criterias (eg values on other fields).

However, your suggested "public profile api" is going to make all the public fields if I read you properly, ie. I wouldn't be able at the template level to decide when I display or not the field.

Am I clearer ?
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: API/ Rest & Anonymous access
July 08, 2009, 01:48:59 pm
So, you overwrite the default setup for search profiles & restrict access?
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: API/ Rest & Anonymous access
July 09, 2009, 05:12:09 am
In that case, I created a custom profiles with the fields set to visible, added a custom template for that profile and added a
I have custom templates that has

{if $session->get('userID') > 0}
Display the fields that are supposed to be visible only by the authenticated users...

{/if}

display those that are visible by everyone
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Pages: [1] 2
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • API/ Rest & Anonymous access

This forum was archived on 2017-11-26.