Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

External services description: Difference between revisions

From MoodleDocs
m (Protected "External services description": Developer Docs Migration ([Edit=Allow only administrators] (indefinite)))
 
(160 intermediate revisions by 14 users not shown)
Line 1: Line 1:
{{Moodle_2.0}}
{{Template:Migrated|newDocId=/docs/apis/subsystems/external/description}}
 
== Purpose ==
This document explains how we describe and where we store the web service functions in Moodle 2.0.
 
We store function descriptions in the component/db/services.php file. Web services functions will be located in  externallib.php files - this file name is not mandatory, but is strongly recommended.
 
Descriptions will be parsed by a service discovery function that will fill the database (extend the current discovery functionalities looking parsing the DB folders).
 
 
=== Administration pages ===
Moodle administrators will be able to manage services. By default all services will be disabled.
 
List of administration functionalities:
* enable a service (all the functions into this service will be available)
* associate a web service user (the user has web service capability) to some services => a user can only call a service that he is associated with
* create a custom service (add and remove functions from this service)
* search easily function by component in order to create a custom service
Administrators will also be able to create a custom service, selecting any existing functions.
 
===external_functions table===
List of web service functions. This table maps the web service name to the actual implementation of that function.
 
 
{| class="nicetable"
! Field
! Type
! Default
! Description
|-
| '''id'''
| int(10)
| auto-incrementing
|
|-
| '''name'''
| varchar(200)
|
| unique name of the external function used in web service protocols - a unique identifier for each function; ex.: core_get_users, mod_assignment_submit
|-
| classname
| varchar(100)
|
| name of the class that contains method implementation; ex.: core_user_external, mod_assignment_external
|-
| methodname
| varchar(100)
|
| static method; ex.: get_users, submit
|-
| classpath
| varchar(255)
| NULL
| optional path to file with class definition - recommended for core classes only, null means use component/externallib.php; this path is relative to dirroot; ex.: user/externallib.php
|-
| component
| varchar(100)
|
| Component where function defined, needed for automatic updates. Service description file is found in the db folder of this component.
|}
 
Detailed function description is stored as a complex PHP array in db/services.php file.
 
===external_services table===
''Service'' is defined as a group of web service functions. The main purpose of these ''services'' is to allow defining of granular access control for multiple external systems.
 
 
{| class="nicetable"
! Field
! Type
! Default
! Description
|-
| '''id'''
| int(10)
| auto-incrementing
|
|-
| '''name'''
| varchar(150)
|
| Name of service (gradeexport_xml_export, mod_chat_export) - appears on the admin page
|-
| enabled
| int(1)
| 0
| service enabled, for security reasons some services may be disabled- administrators may disable any service via the admin UI
|-
| requiredcapability
| varchar(255)
| NULL
| if capability name specified, user needs to have this permission in security context or in system context if context restriction not specified
|-
| restrictedusers
| int(1)
| 1
| 1 means on users explicitly listed in external_services_users may access this service, 0 means any user may use this service
|-
| component
| varchar(100)
| NULL
| Component where service defined - null means custom service defined in admin UI.
|}
 
===external_services_functions table===
Lists all functions that are available in each service.
 
{| class="nicetable"
! Field
! Type
! Default
! Description
|-
| '''id'''
| int(10)
| auto-incrementing
|
|-
| '''externalserviceid'''
| int(10)
|
| foreign key, reference external_services.id
|-
| '''functionname'''
| varchar(200)
|
| name of external service, references external_functions.name; the string value here simplifies service discovery and maintenance
|}
 
===external_services_users table===
Specifies services used by users.
 
{| class="nicetable"
! Field
! Type
! Default
! Description
|-
| '''id'''
| int(10)
| auto-incrementing
|
|-
| '''externalserviceid'''
| int(10)
|
| foreign key, reference external_services.id
|-
| '''userid'''
| int(10)
|
| foreign key, reference user.id
|}
 
 
=== PHP array description ===
 
We need to describe the services in detail, including input and output, so that we can:
 
* help programmers quickly understand what they have to send and what to expect
* validate all incoming data as automatically as possible for security/correctness
* generate WSDL files for SOAP
* generate documentation for other protocols
 
There are three main parts working together to do this:
 
====services.php====
 
In the db/services.php of each component, is a structure something like this to describe the web service functions, and optionally, any larger services built up of several functions.
 
<code php>
$functions = array(
    'moodle_user_create_users' => array(
        'classname'  => 'moodle_user_external',
        'methodname'  => 'create_users',
        'classpath'  => 'user/externallib.php',
        'params'      => 'createusersparams',
        'returns'    => 'createusersreturn'
    )
);
 
$services = array(
    'servicename' => array(
        'functions' => array ('functionname', 'secondfunctionname'),
        'requiredcapability' => 'some/capability:specified',
        'restrictedusers' = >1,
        'enabled'=>0, //used only when installing the services
    )
);
</code>
 
The function name is arbitrary, but it must be globally unique so we highly recommend using the component name as prefix (and "moodle" for core functions).
 
====externallib.php====
 
In the file referenced as the location for the web service function, there are also complete descriptions of the parameters required.
 
<code php>
    $userpreference = new object();
    $userpreference->name =  array(PARAM_ALPHANUMEXT, 'The name of the preference to set');
    $userpreference->value =  array(PARAM_RAW, 'The value of the preference');
 
    $usercustomfields = new object();
    $usercustomfields->name =  array(PARAM_ALPHANUMEXT, 'The name of the custom field (must exist)');
    $usercustomfields->value =  array(PARAM_RAW, 'The value of the custom field');
 
    $usertocreate = new object();
    $usertocreate->username    = array(PARAM_USERNAME, 'Username policy is defined in Moodle security config', REQUIRED);
    $usertocreate->password    = array(PARAM_RAW, 'Moodle passwords can consist of any character', REQUIRED);
    $usertocreate->firstname  = array(PARAM_NOTAGS, 'The first name(s) of the user', REQUIRED);
    $usertocreate->lastname    = array(PARAM_NOTAGS, 'The family name of the user', REQUIRED);
    $usertocreate->email      = array(PARAM_EMAIL, 'A valid and unique email address', REQUIRED);
    $usertocreate->auth        = array(PARAM_AUTH, 'Auth plugins include manual, ldap, imap, etc');
    $usertocreate->confirmed  = array(PARAM_NUMBER, 'Active user: 1 if confirmed, 0 otherwise');
    $usertocreate->idnumber    = array(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution');
    $usertocreate->emailstop  = array(PARAM_NUMBER, 'Email is blocked: 1 is blocked and 0 otherwise');
    $usertocreate->lang        = array(PARAM_LANG, 'Language code such as "en_utf8", must exist on server');
    $usertocreate->theme      = array(PARAM_THEME, 'Theme name such as "standard", must exist on server');
    $usertocreate->timezone    = array(PARAM_ALPHANUMEXT, 'Timezone code such as Australia/Perth, or 99 for default');
    $usertocreate->mailformat  = array(PARAM_INTEGER, 'Mail format code is 0 for plain text, 1 for HTML etc');
    $usertocreate->description = array(PARAM_TEXT, 'User profile description, as HTML');
    $usertocreate->city        = array(PARAM_NOTAGS, 'Home city of the user');
    $usertocreate->country    = array(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ');
    $usertocreate->preferences = array('multiple' => $userpreference);
    $usertocreate->custom      = array('multiple' -> $usercustomfields);
 
    $createusersparams = new object();
    $createusersparams->users  = array('multiple' => $usertocreate);
 
    $createusersreturn = new object();
    $createusersreturn->userids = array('multiple' => PARAM_NUMBER);
</code>
 
Note the use of Moodle-oriented PARAM_XXXX constants to define the format of each field.  These are used by the validation function to clean the data and throw an exception and abort the operation completely if the data changed during cleaning (ie it was unclean).
 
====Params====
 
We use the clean_param function to check data.  We have added some new checks for common Moodle data so that we get better cleaning.  eg
 
<code php>
...
        case PARAM_AUTH:
            $param = clean_param($param, PARAM_SAFEDIR);
            if (exists_auth_plugin($param)) {
                return $param;
            } else {
                return '';
            }
 
        case PARAM_LANG:
            $param = clean_param($param, PARAM_SAFEDIR);
            $langs = get_list_of_languages(false, true);
            if (in_array($param, $langs)) {
                return $param;
            } else {
                return '';  // Specified language is not installed
            }
 
        case PARAM_THEME:
            $param = clean_param($param, PARAM_SAFEDIR);
            if (file_exists($CFG->dirroot.'/theme/'.$param)) {
                return $param;
            } else {
                return '';  // Specified theme is not installed
            }
...
</code>
<nowiki>Insert non-formatted text here</nowiki>
 
=== Function implementation ===
The function are store into servicelib.php classes. These classes can be found anywhere and are referenced by the servicelibpath into the function description. However it would be a common practice to place them in obvious places like a plugin lib folder.
 
<code php>
final class componentname_external {
    static public function methodname ($params) {
        clean_function_params('functioname', $params);
   
    /// specific function code
    /// ...
    }
}
</code>
 
=== Way to fill the database tables ===
The Moodle upgrade will take care of the updates. We will need to add a function into lib/upgradelib.php/upgrade_plugins() that will check all web service description.
 
=== Return values are filtered by the servers ===
Web service function should be able to return whatever they want. Each server should be looking at the web services description and returns the expected values.
 
== Petr's Proposal ==
It can be found [https://docs.moodle.org/en/Development:Web_services_security#New_database_tables here].
 
[[Category:Web Services]]

Latest revision as of 06:12, 22 December 2022

Important:

This content of this page has been updated and migrated to the new Moodle Developer Resources. The information contained on the page should no longer be seen up-to-date.

Why not view this page on the new site and help us to migrate more content to the new site!