Hello,

How do we create a new user on the drupal site using services 3 module using REST and Curl from the external php form.
I mangaed to login into the site from the external php form , But not able to create a new user.
I tried with http://example.com/rest/user/register (REST server url) and passes the user data (name , email, pass) , But while submitting the external php form i am getting this error "The requested URL returned error: 406" . I searched a lot about the error but not able to find the result , One thing i know that the error is coming because of passing wrong parameters .

Any help will be appreciated.

Comments

ygerasimov’s picture

Status: Active » Fixed

I would recommend to use user create method for this. Please use test as a reference about curl options and how arguments should be prepared http://drupalcode.org/project/services.git/blob/refs/heads/7.x-3.x:/test...

Feel free to reopen this issue if have any other questions.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

drupaldrop’s picture

Status: Closed (fixed) » Active

Hello ygerasimov, thanks for the reply , i have follow the test document and try to pass the same parameters , but still i am getting this error "406Auth error The requested URL returned error: 406". Please help me in this. Here is my code.

$services_url = 'http://localhost/test/trunk/rest';

/*
 * Server REST - user.register
 */

// REST Server URL for auth
$request_url = $services_url . '/user';
// User data
$user_data = array(
  'username' => 'test123456',
  'email' => 'test@gmail.com',
  'pass' => 'test',
  'status' => 1,
);

$user_data = http_build_query($user_data);
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Check if registration was successful
if ($http_code == 200) {
  // Convert json response as array
  $register_user = json_decode($response);
}
else {
  // Get error msg
  $http_message = curl_error($curl);
  die('Auth error ' . $http_message);
}

Thanks
- Akash

ygerasimov’s picture

if you send your data as json, then you should encode your arguments with json_encode. So
$user_data = http_build_query($user_data);

should be
$user_data = json_encode($user_data);

Also mention json formatter in your call. So instead of
$request_url = $services_url . '/user';

Do
$request_url = $services_url . '/user.json';

drupaldrop’s picture

Hello Yegerasimov, I have made the changes that you have stated , But still i am getting the same error 406 Auth Error.Do permissions has to do something with this?

now my service url is -> http://localhost/test/trunk/rest/user.json

I have one question in mind in My case we are not defining the name of the services like user.register or node.create but we are depending on the parameters we are passing , so Services know what action to take on the drupal site?.

- Akash

ygerasimov’s picture

yes, you may have problem with permissions. Please make sure when you create a user, you have permission 'administer users'.

Services understand the method you are calling by request type:
POST create
GET retrieve
PUT update
DELETE delete

In your case you do POST request, so services understand it properly.

If you do action (like user/register) you should do POST query to http://localhost/test/trunk/rest/user/register.json

drupaldrop’s picture

Hello Ygerasimov, I tried with the above post query but no luck . So what I did I used this example(http://drupal.org/node/1334758) to test if any other services i am able to call or not . But now i am getting this error "401 Unauthorized: Wrong username or password, or user doesn't have right permission." .I am quite sure about the username and password i am passing is correct , cause i am using administrator credentials , I also gave permission "administer users" to anonymous but still not luck. Also I read README.txt in the services module. I checked the services lib folder and it contains the file spyc.php file which is the required file to use REST server. I also noticed one thing about services authentication module which has a dependencies over "Oauth common" module and this module is not available for drupal 7. so i cant see what service authentication module is for?

drupaldrop’s picture

I installed OAuth module and check the session authentication checkbox in the services administer page now i am able to create a node and can login to the site easily, Now i am moving to register a user on the site ..... X

drupaldrop’s picture

Hello ygerasimov, I am sending user data in below structure.
$user_data = array(
'name' => 'new123',
'email' => 'ab12345@gmail.com',
'pass1' => 'test1',
'pass2' => 'test1',
'status' => 0,
);
But when i print the response of the curl , only the email field in the user registration get refilled with above data , i know the structure is wrong that i am passing, but can't figure out till now the correct structure.

please help.

ygerasimov’s picture

when you register you should send:
array('name' => 'new123', 'mail' => 'new123@email.com', 'pass' => 'password123').

See http://drupalcode.org/project/services.git/blob/refs/heads/7.x-3.x:/test... for example.

drupaldrop’s picture

Thanks Ygerasimov, Finally i am able to register the user on the site.Below is the working code for registering user on the site.

/*
 * Server REST - user.register
 */


// User data
$user_data = array();
$user_data['name'] = 'test'; 
$user_data['mail'] = 'test@example.com';
$user_data['pass'] = 'test12';
$user_data['pass1'] = 'test12';
$user_data['status'] = 1;

// cURL code
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/adw/trunk/rest/user/register");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $user_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($http_code == 200) {
  print 'user registered';
 }
else {
  print 'user not registered';
 }

Now i moving to include a membership on the user registration page , So when user registered on the site some payment will get deducted from his account, I am using membership suite module to include membership on the user register page and through services i am going to fill the form including membership ......X

ygerasimov’s picture

Status: Active » Fixed

Congrats! Marking this issue fixed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

arcane’s picture

Building on the example provided above, I added required fields to the user account, which display on the user registration form in Drupal 7. How would I go about pre-populating these fields in the user data array? Is this allowed?

Sample Required field

[field_user_first] => Array
        (
            [und] => Array
                (
                    [0] => Array
                        (
                            [value] => test
                            [format] => 
                            [safe_value] => test
                        )

                )

        )

I tried add this to the user data array, but it didn't work when I tried to to add a user through the script:

// User data
$user_data = array();
$user_data['name'] = 'test9';
$user_data['mail'] = 'test9@example.com';
$user_data['pass'] = 'test12';
$user_data['pass1'] = 'test12';
$user_data['status'] = 1;
$user_data['field_user_first'] = array(
                                      'und' =>
                                      array (
                                        0 =>
                                        array (
                                          'value' => 'test',
                                          'format' => NULL,
                                          'safe_value' => 'test',
                                        ),
                                      ),
                                    );
arcane’s picture

in sites/all/modules/services/resources/user_resource.inc, I don't see any code that would map form state values for added fields (unless I'm wrong?)

/**
 * Create a new user.
 *
 * This function uses drupal_form_submit() and as such expects all input to match
 * the submitting form in question.
 *
 * @param $account
 *   A object containing account information. The $account object should
 *   contain, at minimum, the following properties:
 *     - name (user name)
 *     - mail (email address)
 *     - pass (plain text unencrypted password)
 *
 *   These properties can be passed but are optional
 *     - status (0 for blocked, otherwise will be active by default)
 *     - notify (1 to notify user of new account, will not notify by default)
 *
 *  Roles can be passed in a roles property which is an associative
 *  array formatted with '<role id>' => '<role id>', not including
 *  the authenticated user role, which is given by default.
 *
 * @return
 *   The user object of the newly created user.
 */
function _user_resource_create($account) {
  // Adds backwards compatability with regression fixed in #1083242
  $account = _services_arg_value($account, 'account');

  // Load the required includes for saving profile information
  // with drupal_form_submit().
  module_load_include('inc', 'user', 'user.pages');

  // register a new user
  $form_state['values'] = $account;
  $form_state['values']['pass'] = array(
    'pass1' => $account['pass'],
    'pass2' => $account['pass'],
  );  
  $form_state['values']['op'] = variable_get('services_user_create_button_resource_create', t('Create new account'));

  // execute the register form
  drupal_form_submit('user_register_form', $form_state);
  // find and store the new user into the form_state
  if(isset($form_state['values']['uid'])) {
    $form_state['user'] = user_load($form_state['values']['uid']);
  }

  // Error if needed.
  if ($errors = form_get_errors()) {
    return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
  }
  else {
    $user = array('uid' => $form_state['user']->uid);
    if ($uri = services_resource_uri(array('user', $user['uid']))) {
      $user['uri'] = $uri;
    }   
    return $user;
  }
}
aklump’s picture

I wanted to share my experience with getting this to work.

First point learned:
I was going round and round getting a 406, when I realized that I had some required fields on our registration form.

If you have any required fields, you must send those in your post array.

Second point learned
Even though all required fields were being sent I still got a 406... why? Mollom. We have mollom set up on our registration form and this leads to a 406 (I'm not sure yet how to get around this). When I disabled mollom the 406 disappeared and the user was created.

Captcha form elements, which are required, must be filled in, or disabled.

How to send field values
I thought I'd paste the array I'm sending, which shows how to send fields

<?php
$account = array(
  'name' => 'gamma',
  'pass' => 'gammapass',
  'mail' => 'gamma@gamma.com',
  'notifiy' => 1,
);
$account['field_first_name']['und'][0]['value'] = 'Gamma';
$account['field_last_name']['und'][0]['value'] = 'Smith';
?>
aklump’s picture

Follow up post to #16: How I got around mollom when creating users through the API call.

In the authentication function I set a session var:

$_SESSION['my_module']['active_api_call'] = TRUE

Then in a hook_form_alter I test for that variable if true and then hide mollom form elements:

<?php
/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, $form_state, $form_id) {
  // Remove mollom protection on forms when an api user is accessing them
  if ($_SESSION['my_module']['active_api_call'] = TRUE && array_key_exists('mollom', $form)) {
    // Remove validate and submit functions
    $form_keys = array('#validate', '#submit');
    foreach ($form_keys as $form_key) {
      foreach ($form[$form_key] as $key => $func) {
        if (strpos($func, 'mollom_') === 0) {
          unset($form[$form_key][$key]);
        }
      }
    }
    // Remove the mollom array
    unset($form['mollom']);
  }
}
?>
kaido.toomingas’s picture

What I learned..
You can inspect user register page and these values what you gonna submit are these values what you see when you inspect name attribute.
So

<input type="text" maxlength="60" <strong>name="name"</strong> id="edit-name" size="60" value="" class="form-text required">
<input type="text" maxlength="64" name="mail" id="edit-mail" size="60" value="" class="form-text required">
<input type="text" maxlength="64" name="conf_mail" id="edit-conf-mail" size="60" value="" class="form-text required">

would come
values => name=myusername, mail=mymail@mail.com, conf_mail=mymail@mail.com, status=1 (status 1 will make user logged active).
And now (Drupal 6) post these values to http://somedomail.com/?q=api/user/register.json
And now (Drupal 7) post these values to http://somedomail.com/api/user/register.json

mstrelan’s picture

Issue summary: View changes

Another way to disable mollom:

<?php
function _MYMODULE_disable_mollom() {
  if (function_exists('_mollom_status')) {
    $static_cache = &drupal_static('_mollom_status', array());
    $testing_mode = (int) variable_get('mollom_testing_mode', 0);
    $status = &$static_cache[$testing_mode];
    $status['keys'] = FALSE;
    $status['response'] = NULL;
  }
}
?>

Can be called any time after mollom_init(), so doesn't have to be specifically in a form alter.

mstrelan’s picture

Also, to those struggling to send field data...

Instead of

<?php
$account['field_first_name']['und'][0]['value'] = 'Gamma';
$account['field_last_name']['und'][0]['value'] = 'Smith';
?>

I am using

<?php
$account['field_first_name[und][0][value]'] = 'Gamma';
$account['field_last_name[und][0][value]'] = 'Smith';
?>
Anonymous’s picture

I got the result in core php using curl function but need to check using poster or postman

$account['field_first_name[und][0][value]'] = 'Gamma'; how to set this value in poster application

parameter section

field_first_name[und][0][value] = 'Gamma' still i get
this error

field_name_first][und][0][value":"First Name field is required

Hajdarevic’s picture

Your comments above are very helpfully and I have made a custom php script with which my visitors are able to register through a custom form.

After that I have created a custom user profiles pages where all fields of currently logged user are automatically filled... Now I want to find a way to update those fields with PHP cURL,

So, that means when user go to custom user profile page he/she will be able to change lets say 'e-mail', 'city', 'country' and so on and click Submit. After that fields needs to be updated...

Any kind of help will be appreciated.

Thanks

raj45’s picture

I was getting the 406 error when trying to create a new node, which had a required field, which didn't have a default value. After setting a default value, it now works as designed.

damien_th’s picture

Here is my code to create an user using Rest Services coming OOTB from Drupal:

Prerequisites:

  • Rest Services module must be enabled
  • Rest UI module must be installed and enabled
  • Perform this as an administrator or adjust REST Services rights in Extend => Rest Services => Rights
  • In configuration => REST, enable resource "user" for POST with hal+json, and the authentication prefer you prefer. In my example below, it is Basic Authentication.

Here is my Query:
POST your.drupal.website/entity/user?_format=hal_json

Headers:

Content-Type: application/hal+json
X-CSRF-Token: <your_token_retrieved_from_your.drupal.website/rest/session/token>
Authorisation: Basic xxxxxxxxxxxxxxxxxxxxxxx

Body:

{
    "_links": {
      "type": {
        "href": "http://your.drupal.website/rest/type/user/user"
      }
    },
	"name":[{"value":"test"}],
	"mail":[{"value":"test@test.fr"}],
	"roles":[{"target_id":"administrator"}],
	"pass":"testpassword"
}
Chris Charlton’s picture

Ugh. #20 was right for me today. Odd. And undesirable.

Anyone have a tip on how to make this cleaner?

jordiserra’s picture

I tried #24 and it doesn't work for me. I'm trying to call /entity/user rest service from D7, but it keeps me saying Access denied, no matter how I try to access. I tried using basic auth with a specific D8 user, with super user credentials, without credentials (as anonymous user)...

However, I can create nodes and taxonomy terms using /entity/node and /entity/taxonomy_term endpoints.

Any ideas about what am I doing wrong?

Thanks

EDIT: Answering myself, finally I solved my problem and it was not related to the process explained in #24. It was a problem with a field, giving, as a result a not valid entity.