Creating your own API plugins

api plugin structure

Note : This article was updated on 2nd July 2017 to describe new "auth free" functionality that will be available from Jomres 9.9.6 onwards.

 

We have deliberately made it as simple as possible to create your own API plugins for Jomres.

The functionality your plugin supplies can be as simple or as complicated as you need it to be, but there are a few files that are required for it to run :

  • All Jomres plugins need a plugin_info.php file to describe the system to the plugin manager.
  • A 00005 script ( for example j00005api_feature_favourites.class.php ) to include a language file. Most Jomres plugins that require a language file will have one of these, just look at one of them if in any doubt as to how they work.
  • A scopes.json file, which is a JSON description of the permissions the user needs to give to the Client so that they can access the plugin's functionality.
  • Optional : auth_free.json

 

scopes.json

Here is an example of what's in a scopes.json file.


{
    "_OAUTH_SCOPE_CATEGORY_USER": [{
        "scope": "favourites_get",
        "user_type": "user",
        "definition": "_OAUTH_SCOPE_FAVOURITES_GET",
        "description": "_OAUTH_SCOPE_FAVOURITES_GET_DESC"
    }, {
        "scope": "favourites_set",
        "user_type": "user",
        "definition": "_OAUTH_SCOPE_FAVOURITES_SET",
        "description": "_OAUTH_SCOPE_FAVOURITES_SET_DESC"
    }]
}

_OAUTH_SCOPE_CATEGORY_USER refers to the parent category, currently this will either be _OAUTH_SCOPE_CATEGORY_USER or _OAUTH_SCOPE_CATEGORY_PROPERTIES ( "User permissions" & "Property permissions" ). This is purely for separating functionality in the Edit Client page.

Scope is important. In this example we've stuck with two simple descriptions "favourites_get" and "favourites_set", which means that only API clients that have been given permission to "Get favourites" can download the property uids that the user has set as a favourite. In theory you could have as many or as few scopes as you want, but we recommend you have at least one "get" scope and one "set" scope.

Any registered user can give rights to API Clients in the user "user_type" category, but only property managers can give API Clients "manager" access rights. There is also a user_type "super", which allows you to create functionality that's only available to Super Property Managers.

_OAUTH_SCOPE_FAVOURITES_GET & _OAUTH_SCOPE_FAVOURITES_GET_DESC refer to language strings that are stored in the language file that are included when you include a 00005 script with your plugin (see above).

 

There are several sub-directories, which is where the Jomres functionality will look for your API scripts. Ignoring the "language" directory where you language file(s) are kept, the directories are DELETE, GET, POST & PUT. If an app is sending a Delete request, then the script that is run will be in the DELETE directory. "The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, PATCH, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively." See http://www.restapitutorial.com/lessons/httpmethods.html

auth_free.json

In Jomres 9.9.6 we are adding support for Authentication Free access to the REST API. This gives plugins the option to declare themselves as "authentication free" through an auth_free.json file.

The addition of this functionality opens up the scope of user access to your Jomres REST API by allowing anybody to search and retrieve information from your site. This removes potential barriers to adoption of your service.

 

Clients accessing an authentication free api feature ( such as Api Feature Search ) will not need to supply a Client ID/Secret keypair.

The auth_free.json file will need to contain

{
    "auth_free": true
}

Users creating client id/secret pairs will not be able to select this auth free api features through the Client creation page, because it's automatically available to everybody.

 

Note : individual endpoints in api features can still restrict access through the use of validate_scope::validate('xxxxxxx_get');

 

Anatomy of an API plugin

 

The script in this example would be run when a GET request is sent to the API  www.example.com/jomres/api/favourites/

 

Flight::route('GET /favourites', function()
    {
    validate_scope::validate('favourites_get');
        
    $conn = Flight::db();
    
    $stmt = $conn->prepare( 'SELECT property_uid FROM '.Flight::get("dbprefix").'jomcomp_mufavourites WHERE my_id = :my_id' );
    $stmt->execute([ 'my_id' => Flight::get("user_id") ]);
    $property_uids = array();
    while ($row = $stmt->fetch())
        {
        $property_uids[] = $row['property_uid'];
        }
    $conn = null;
    
    Flight::json( $response_name = "ids" , $property_uids);
    });


Let's look at the pertienent lines in the script to describe what they do :

defined( '_JOMRES_INITCHECK' ) or die( '' );

This ensures that the call to the API has come through the Jomres API index.php and doesn't get called by itself. It is a security feature.

Flight::route('GET /favourites', function()

Jomres uses a micro-framework called Flight PHP ( http://flightphp.com/ ) because it's very small, fast and offers routing functionality. This example is basically a "route" script for Flight. To see the options that can be passed to a route, please see http://flightphp.com/learn#routing


validate_scope::validate('favourites_get');

Confirm that the client has the rights to access this scope.

 

$response = Flight::request_response();

Sets up the response object.

$conn = Flight::db();

This calls the PDO object that's already been setup for talking to mysql.

The next few lines setup a prepared query for mysql to pull the user's favourites from the database. Describing this is outside of the scope of this article.


Flight::json( $response_name = "ids" , $property_uids);

These lines set the value of the response, depending on whether or not any data was found. Generally you'll probably only want to send two responses, either the requested data or a 204 response code, which confirms that the script ran correctly, but there's no data to return. This is the data that's returned in the "Envelope".

Every authenticated response is contained by an envelope. That is, each response has a predictable set of keys with which you can expect to interact. The json response of the envelope typically looks like

{
"meta":{
	"code":200
	},
"data":{
	"xxx": yyy
	}}

 

So in this example the "data" section will have "ids" which in turn will be an array of property uids.

 Postman get favourites screencap

Code re-use

It is possible to get the script to call Jomres through the call_self class, like so :


$call_self = new call_self();
$elements = array(
    "method"=>"GET",
    "request"=>"properties/all",
    "data"=>array()
    );
$result = json_decode($call_self->call($elements));

This assumes that the Client has Properties Get rights.

 

You don't want to constantly re-invent the wheel, Jomres already does a lot so to re-use the Jomres framework's code to do something you can call Jomres functions directly once you've included the framwork code, like so

 

if (!isset($language))
    $language = "en-GB";
 $_REQUEST['jomreslang'] = $language;
 require_once("../framework.php");

 

For example, to use the search functionality we've done this

 

$_REQUEST['stars'] = $stars;
 
$MiniComponents =jomres_getSingleton('mcHandler');
$result = $MiniComponents->specificEvent('06110',"ajax_search_composite");

 

 

which allows us to easily search by stars, as it returns a result that's easily maniplulated in our own off-site code, the j06110ajax_search_composite is already capable of searching by stars.