Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-68034

Webservice core_user_create_users is not extendable

    XMLWordPrintable

    Details

    • Testing Instructions:
      Hide

      1. Create a webservice custom plugin, that extend core_user_external. Example:

      // Example: local/mywebservices/version.php
      defined('MOODLE_INTERNAL') || die();
      $plugin->version = 2020022416;
      $plugin->requires = 2018051709;
      $plugin->component = 'local_mywebservices';
      $plugin->maturity = MATURITY_BETA;
       
       
      // Example: local/mywebservices/db/services.php
      $functions = array(
          'local_mywebservices_create_users' => array(
              'classname'    => 'local_mywebservices_external',
              'methodname'   => 'create_users',
              'classpath'    => 'local/mywebservices/class/external.php',
              'description'  => 'Create users (including phone1).',
              'type'         => 'write',
              'capabilities' => 'moodle/user:create'
          )
      );
       
       
      // Example: local/mywebservices/class/external.php
      class local_mywebservices_external extends core_user_external {
          public static function create_users_parameters() {
              $parameters = parent::create_users_parameters();
              $parameters->keys['users']->content->keys['phone1'] = new external_value(
                  core_user::get_property_type('phone1'),
                  'The phone number of the user',
                  VALUE_OPTIONAL);
              return $parameters;
          }
      }
      

      2. Enable webservices and create a webservice user and token in the administration, to allow the use of the custom webservice. (https://docs.moodle.org/38/en/Using_web_services). The user related to the token must have the capabilities to create and update users, as we want to extend the webservices core_user_create_users and core_user_update_users.

      3. Call your custom webservice. Example:

      POST /webservice/rest/server.php?moodlewsrestformat=json&wstoken=TOKEN&wsfunction=local_mywebservices_create_users HTTP/1.1
      Host: mdl-local.docker.test
      Content-Type: application/x-www-form-urlencoded
      Authorization: Basic d3M6d3M=
       
      users%5B0%5D%5Busername%5D=test-username&users%5B0%5D%5Bpassword%5D=test-password-123&users%5B0%5D%5Bfirstname%5D=test-firstame&users%5B0%5D%5Blastname%5D=test-lastname&users%5B0%5D%5Bemail%5D=test-email%40example.com&users%5B0%5D%5Bphone1%5D=0123456789

      As for the webservices we are extending, the request must be POST.
      Any post webform and application to forge POST request can do the job. I personally like postman to do testing.

      Without the correction:
      Notice that the webservice returns an "invalid parameters error"

      With the correction
      Notice that new optional field (phone1) of the new created user is filled.

      Same process for update.

      Show
      1. Create a webservice custom plugin, that extend core_user_external . Example: // Example: local/mywebservices/version.php defined('MOODLE_INTERNAL') || die(); $plugin->version = 2020022416; $plugin->requires = 2018051709; $plugin->component = 'local_mywebservices'; $plugin->maturity = MATURITY_BETA;     // Example: local/mywebservices/db/services.php $functions = array( 'local_mywebservices_create_users' => array( 'classname' => 'local_mywebservices_external', 'methodname' => 'create_users', 'classpath' => 'local/mywebservices/class/external.php', 'description' => 'Create users (including phone1).', 'type' => 'write', 'capabilities' => 'moodle/user:create' ) );     // Example: local/mywebservices/class/external.php class local_mywebservices_external extends core_user_external { public static function create_users_parameters() { $parameters = parent::create_users_parameters(); $parameters->keys['users']->content->keys['phone1'] = new external_value( core_user::get_property_type('phone1'), 'The phone number of the user', VALUE_OPTIONAL); return $parameters; } } 2. Enable webservices and create a webservice user and token in the administration, to allow the use of the custom webservice. ( https://docs.moodle.org/38/en/Using_web_services ). The user related to the token must have the capabilities to create and update users, as we want to extend the webservices core_user_create_users and core_user_update_users. 3. Call your custom webservice. Example: POST /webservice/rest/server.php?moodlewsrestformat=json&wstoken=TOKEN&wsfunction=local_mywebservices_create_users HTTP/1.1 Host: mdl-local.docker.test Content-Type: application/x-www-form-urlencoded Authorization: Basic d3M6d3M=   users%5B0%5D%5Busername%5D=test-username&users%5B0%5D%5Bpassword%5D=test-password-123&users%5B0%5D%5Bfirstname%5D=test-firstame&users%5B0%5D%5Blastname%5D=test-lastname&users%5B0%5D%5Bemail%5D=test-email%40example.com&users%5B0%5D%5Bphone1%5D=0123456789 As for the webservices we are extending, the request must be POST. Any post webform and application to forge POST request can do the job. I personally like postman to do testing. Without the correction: Notice that the webservice returns an "invalid parameters error" With the correction Notice that new optional field (phone1) of the new created user is filled. Same process for update.
    • Workaround:
      Hide

      Duplicate hundreds of lines of code...

      • core_user_external::create_users_parameters
      • core_user_external::create_users
      • core_user_external::update_users_parameters
      • core_user_external::update_users
      Show
      Duplicate hundreds of lines of code... core_user_external::create_users_parameters core_user_external::create_users core_user_external::update_users_parameters core_user_external::update_users
    • Affected Branches:
      MOODLE_38_STABLE
    • Pull Master Branch:

      Description

      I created a plugin to have custom external webservices to create and update users with additional fields (such as optional phone1, department, institution, ...).

      To do that, extending the class \core_user_external and overriding the method \core_user_external::create_users_parameters seems the right, good enough solution.
      (user/externallib.php)

      But the methods create_users and update_users do calls with self to:

      • self::create_users_parameters()
      • self::update_users_parameters()

      Instead, they should call these methods with static:

      • static::create_users_parameters()
      • static::update_users_parameters()

      This way, the extended method wouldn't be dead code.

      Looks like a simple mistake, or just something that was not anticipated.
      I tested the fix, and everything works perfect with it.

      Diff: https://github.com/moodle/moodle/compare/master...liip-elearning:MDL-68034

        Attachments

          Activity

            People

            Assignee:
            Unassigned
            Reporter:
            mcornut Cornut Matthieu
            Peer reviewer:
            Sara Arjona (@sarjona)
            Participants:
            Component watchers:
            Amaia Anabitarte, Carlos Escobedo, Ferran Recio, Sara Arjona (@sarjona), Víctor Déniz Falcón, Juan Leyva, Amaia Anabitarte, Carlos Escobedo, Ferran Recio, Sara Arjona (@sarjona), Víctor Déniz Falcón
            Votes:
            5 Vote for this issue
            Watchers:
            1 Start watching this issue

              Dates

              Created:
              Updated:

                Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0 minutes
                0m
                Logged:
                Time Spent - 35 minutes
                35m