ODS Controllers

The ODS provide an controllers (API) to manipulate the user accounts as well as instances, and instances specific data. The controllers can be accessed via REST using authentication based on OAuth, sessions or password hash. The details are presented bellow.

Access point

The API can be accessed via REST using http://host:port/ods/api/[method]. Parameters specific to each method are given as URL parameters if using GET, as www-url-encoded or multipart/form-data if using POST.

The API can be accessed via UI page using http://host:port/ods/oauth_test.vsp.

Authentication

Most API calls which modify data, i.e., IUD operations, need authentication; thus the request should contain OAuth authentication, or session or password hash. The user account used to authenticate in either case MUST have relevant access to the ODS object. This is done by having owner or author membership to the given application.

OAuth

The user account for authentication must have OAuth tokens generated via ODS -> Settings -> OAuth keys. This UI provides a list of all applications to which the user has access (i.e., he is member or owner). If an instance needs to be accessed with OAuth, user simply selects the instance from the list and clicks 'generate keys'. The generated consumer key & token will be associated to the active ODS user account and selected application instance.

Once a consumer token is available, the sequence below must be done in order to establish an authorized session:

  1. client uses request_token to get a token/secret pair for establishing session using consumer token
  2. client asks OAuth server to authorize the token from step 1
  3. using authorized token from step 1, client asks OAuth server for authentication token
  4. with authentication token from step 3, clients can access instance data associated with the consumer token from step 1

To demonstrate the above, we supply a simple client written in VSP:


<html>
<?vsp
    declare consumer_key, consumer_secret, oauth_token, oauth_secret, signature, timest, nonce varchar;
    declare srv, res, signature_base, ret_url, url, tmp, sid varchar;
    declare meth, pars any;
    consumer_key := {?'key'};
    srv := sprintf ('http://localhost:%s/OAuth/', server_http_port ());
    sid := null;
    res := '';

    sid :=  {?'sid'};
    if (sid = '')
      sid := null;  
    else
      {
        -- if selected token is not same as one from the session we need to get new authentication token
        if (consumer_key <> OAUTH..get_consumer_key (sid))
     {
       OAUTH..session_terminate (sid);
            sid := null;
     }
      }

    meth := get_keyword ('meth', params, 'weblog.post.new');;
    pars := get_keyword ('pars', params, 'inst_id=15&title=testing&description=Some test post');;

    if ({?'rt'} is not null and sid is null) -- request new token for the session
      {
   url := srv||'request_token';
   url := OAUTH..sign_request ('GET', url, '', consumer_key, sid);
        res := http_get (url);
   sid := OAUTH..parse_response (sid, consumer_key, res);
   OAUTH..set_session_data (sid, params);
   ret_url := sprintf ('http://localhost:%s/oauth/oauth_client.vsp?ready=%U', server_http_port (), sid);
   -- call authorize
        url := sprintf ('%sauthorize?oauth_token=%U&oauth_callback=%U', srv, OAUTH..get_auth_token (sid), ret_url);
   http_status_set (301);
        http_header (sprintf ('Location: %s\r\n', url));
        return;
      }
    else if ({?'ready'} is not null) -- get access token
      {
   -- we go here when token above is authorized
        sid := {?'ready'};
   url := srv||'access_token';
   consumer_key := OAUTH..get_consumer_key (sid);
   url := OAUTH..sign_request ('GET', url, '', consumer_key, sid);
        res := http_get (url);
   sid := OAUTH..parse_response (sid, consumer_key, res);

      }
    if (sid is not null) -- access token is ready, and we can call API
      {
        -- here we are ready to call service
   if ({?'rt'} is null)
          {
            tmp := OAUTH..get_session_data (sid);
            pars := get_keyword ('pars', tmp, pars);
       meth := get_keyword ('meth', tmp, meth);
     }
   url := sprintf ('http://localhost:%s/ods/api/%s', server_http_port (), meth);
   tmp := split_and_decode (pars);
   params := '';
   for (declare i,l int, l:=length (tmp); i < l; i := i + 2)
      {
        params := params || sprintf ('%U=%U&', tmp[i], tmp[i+1]);
      }
   --params := sprintf ('inst_id=%d&description=%U&title=%U', 15, 'Some test post', 'testing');
   consumer_key := OAUTH..get_consumer_key (sid);
   url := OAUTH..sign_request ('GET', url, params, consumer_key, sid);
        res := http_get (url);
        --dbg_obj_print (res);
      }
?>
    <head><title>OAuth Client</title></head>
    <body>
   <h1>OAuth client for ODS Controllers</h1>
   <form method="POST" action="oauth_client.vsp">
   <input type="hidden" name="sid" value="<?V sid ?>"/>
   APPLICATION : <br/> <select name="key">
   <?vsp for select a_name, a_key from OAUTH..APP_REG do { ?>
            <option value="<?V a_key ?>" <?vsp if (consumer_key = a_key) http ('selected'); ?>><?V a_name ?></option>
   <?vsp } ?>
              </select>
   <?vsp
   if (sid is not null) http (sprintf (' TOKEN: %s', OAUTH..get_auth_token (sid)));
   ?>
   <br/>
   ODS API: <br/><input type="text" name="meth" value="<?V meth ?>" size=50/> <br/>
   PARAMETERS: <br/> <textarea name="pars" rows="5" cols="50"><?V pars ?></textarea> <br/>
        <input type="submit" value="Execute" name="rt"/><br/>
   </form>
   RESULT:
   <hr/>
   <pre><?V res ?></pre>
    </body>
</html>

The following is a sample session recorded with the client above :


GET /OAuth/request_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b8333607ed
c5f36&oauth_nonce=b8f1089077cbce6e&oauth_signature_method=HMAC-SHA1&oauth_times
tamp=1211212829&oauth_version=1.0&oauth_signature=V1zmk757LBHcmqVJ6obMhNX5hKA%3
D HTTP/1.1
Host: localhost:8890

HTTP/1.1 200 Ok
Content-Length: NNN
<CR/LF>
oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth_token_secret=M...

GET /OAuth/authorize?oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth
_callback=http%3A//localhost%3A8890/oauth/oauth_client.vsp%3Fready%3D00c874b2fa
b2f6424008b5064fe83e88 HTTP/1.1
Host: localhost:8890

HTTP/1.1 301 Moved
Location: /ods/oauth_authorize.vspx?....

GET /OAuth/access_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b8333607edc
5f36&oauth_nonce=242cc4875a0059f6&oauth_signature_method=HMAC-SHA1&oauth_timest
amp=1211212831&oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth_versi
on=1.0&oauth_signature=sqs/8nmNNnNJiZ/eBa688uNeg9o%3D HTTP/1.1
Host: localhost:8890

HTTP/1.1 200 Ok
Content-Length: NNN
<CR/LF>
oauth_token=N..&oauth_token_secret=M...


GET /ods/api/weblog.post.new?description=Some%20test%20post&inst_id=15&oauth_co
nsumer_key=50082d0fb861b0e6e67d5d986b8333607edc5f36&oauth_nonce=2f4765d20664e69
6&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1211213321&oauth_token=db83a
37d74faf53edc8ed56d418ded3a70fcc0bc&oauth_version=1.0&title=testing&oauth_signa
ture=oocIyr6kgoEQkC3WVwzvl6w62W4%3D HTTP/1.1
Host: localhost:8890


HTTP/1.1 200 Ok
Content-Length: NNN
<CR/LF>
<result><code>1&lt/code></result>

Session based

The request to the API in this type of authentication must have 'sid' & 'realm' via 'user.authenticate' method:

To get session id:


curl -i "http://localhost:8890/ods/api/user.authenticate?user_name=demo&passwor
d_hash=fe1774cfea9f7b402796751a4616c04a6f010ecb"
HTTP/1.1 200 OK
Content-Type: text/plain; charset="UTF-8"
Content-Length: 32

bfb2b13e4218a99f65b956eb6ba657cb << SID

Perform weblog.post.new API call:


curl -i "http://localhost:8890/ods/api/weblog.post.new?title=test&description=S
ome%20test%20post&inst_id=15&sid=bfb2b13e4218a99f65b956eb6ba657cb&realm=wa"
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: text/xml; charset="UTF-8"
Content-Length: 53
<CR/LF>
<result><code>1&lt/code></result>

password hash

This approach is similar to above, but instead of sid and realm we just pass as parameters to request the user_name & password_hash .

Response format

IUD operations

The IUD methods return an XML response with code & message format follows:

On success

<result><code>NNN</code><message>human readable explanation if applicable</message></result>

On failure

<failed><code>NNN</code><failed>human readable explanation</message></failed>

Search (get)

The search methods returns results in RDF format according to FOAF, SIOC and SIOC types module ontology. See ODS RDF model.

API methods

All APIs are acting on behalf of the user who established authentication, i.e., the user which is authorized. The APIs where user is subject of removal or freeze as well as registration the user name is passed as parameter. Therefore user.register, user.delete would need user name as input parameter where user.update, instance.create will use the user from authentication information.

Framework


user.register (
    name varchar,
    password varchar,
    email varchar
    )
user.authenticate (
    user_name varchar,
    password_hash varchar
    )
user.update (user_info any)
user.password_change (new_password varchar)
user.delete (name varchar)
user.enable (name varchar)
user.disable (name varchar)
user.get (name varchar)
user.search (pattern varchar)
user.invite (
    friends_email varchar,
    custom_message varchar default ''
    )
user.invitation (
    invitation_id varchar,
    approve int
    )
user.invitations.get ()
user.relation_terminate (friend varchar)
user.tagging_rules.add (
    rulelist_name varchar,
    rules any,
    is_public int default 1
    )
user.tagging_rules.delete (rulelist_name varchar)
user.tagging_rules.update (
    rulelist_name varchar,
    rules any
    )
user.hyperlinking_rules.add (rules any)
user.hyperlinking_rules.update (rules any)
user.hyperlinking_rules.delete (rules any)
user.annotation.add (
    claimIri varchar,
    claimRelation varchar,
    claimValue varchar
    )
user.annotation.delete (
    claimIri varchar,
    claimRelation varchar,
    claimValue varchar
    )

instance.create (
    type varchar,
    name varchar,
    description varchar,
    model int,
    public int
    )
instance.update (
    inst_id int,
    name varchar,
    description varchar,
    model int,
    public int
    )
instance.delete (inst_id int)
instance.freeze (name varchar)
instance.unfreeze (name varchar)
instance.join (inst_id int)
instance.disjoin (inst_id int)
instance.join_approve (
    inst_id int,
    uname varchar
    )
instance.notification.services ()
instance.notification.set (
    inst_id int,
    services any
    )
instance.notification.cancel (
    inst_id int,
    services any
    )
instance.notification.log (inst_id int)
instance.get (inst_id int)
instance.get.id (name varchar)

site.search (
    pattern varchar,
    options any
    )

Briefcase

Weblog

Addressbook

Bookmarks

Polls

Calendar

Feed Manager

Webmail

Discussion

Gallery

Wiki

Messenger

References

CategoryODS CategoryVirtuoso