. "2017-06-13T05:37:10Z" . . . . "VirtuosoOdsControllers" . . . "VirtuosoOdsControllers" . . . . . "2017-06-13T05:37:10Z" . . . . . . . . . . . . . "2017-06-13T05:37:10.057266"^^ . . . . "2017-06-13T05:37:10.057266"^^ . . . . . . . . . . "ce08339f1a5ed6b8b9bee11f727952f7" . . . . . . . . . "VirtuosoOdsControllers" . . . . "%VOSWARNING%\n\n\n%TOC%\n\n---+ ODS Controllers\n\nThe ODS provide an controllers (API) to manipulate the user accounts as well as \ninstances, and instances specific data.\nThe controllers can be accessed via REST using authentication based on OAuth, \nsessions or password hash. The details are presented bellow. \n\n---++ Access point\n\nThe API can be accessed via REST using \nhttp://host:port/ods/api/[method]. Parameters \nspecific to each method are given as URL parameters if using \nGET, as www-url-encoded \nor multipart/form-data if using \nPOST. \n\nThe API can be accessed via UI page using \nhttp://host:port/ods/oauth_test.vsp.\n\n---++ Authentication\n\nMost API calls which modify data, i.e., IUD operations, need authentication; thus \nthe request should contain OAuth authentication, or session or password hash. The \nuser account used to authenticate in either case MUST have relevant access to the \nODS object. This is done by having owner or author membership to the given application. \n\n---+++ OAuth \n\nThe user account for authentication must have OAuth tokens generated via ODS -> \nSettings -> OAuth keys. This UI provides a list of all applications to which the \nuser has access (i.e., he is member or owner). If an instance needs to be accessed \nwith OAuth, user simply selects the instance from the list and clicks 'generate keys'. \nThe generated consumer key & token will be associated to the active ODS user account \nand selected application instance. \n\nOnce a consumer token is available, the sequence below must be done in order to \nestablish an authorized session:\n\n 1. client uses request_token to get a token/secret pair for \nestablishing session using consumer token\n 2. client asks OAuth server to authorize the token from step 1\n 3. using authorized token from step 1, client asks OAuth server for \nauthentication token \n 4. with authentication token from step 3, clients can access instance data \nassociated with the consumer token from step 1\n\n\nTo demonstrate the above, we supply a simple client written in VSP:\n\n\n<html>\n<?vsp\n declare consumer_key, consumer_secret, oauth_token, oauth_secret, signature, timest, nonce varchar;\n declare srv, res, signature_base, ret_url, url, tmp, sid varchar;\n declare meth, pars any;\n consumer_key := {?'key'};\n srv := sprintf ('http://localhost:%s/OAuth/', server_http_port ());\n sid := null;\n res := '';\n\n sid := {?'sid'};\n if (sid = '')\n sid := null; \n else\n {\n -- if selected token is not same as one from the session we need to get new authentication token\n if (consumer_key <> OAUTH..get_consumer_key (sid))\n {\n OAUTH..session_terminate (sid);\n sid := null;\n }\n }\n\n meth := get_keyword ('meth', params, 'weblog.post.new');;\n pars := get_keyword ('pars', params, 'inst_id=15&title=testing&description=Some test post');;\n\n if ({?'rt'} is not null and sid is null) -- request new token for the session\n {\n url := srv||'request_token';\n url := OAUTH..sign_request ('GET', url, '', consumer_key, sid);\n res := http_get (url);\n sid := OAUTH..parse_response (sid, consumer_key, res);\n OAUTH..set_session_data (sid, params);\n ret_url := sprintf ('http://localhost:%s/oauth/oauth_client.vsp?ready=%U', server_http_port (), sid);\n -- call authorize\n url := sprintf ('%sauthorize?oauth_token=%U&oauth_callback=%U', srv, OAUTH..get_auth_token (sid), ret_url);\n http_status_set (301);\n http_header (sprintf ('Location: %s\\r\\n', url));\n return;\n }\n else if ({?'ready'} is not null) -- get access token\n {\n -- we go here when token above is authorized\n sid := {?'ready'};\n url := srv||'access_token';\n consumer_key := OAUTH..get_consumer_key (sid);\n url := OAUTH..sign_request ('GET', url, '', consumer_key, sid);\n res := http_get (url);\n sid := OAUTH..parse_response (sid, consumer_key, res);\n\n }\n if (sid is not null) -- access token is ready, and we can call API\n {\n -- here we are ready to call service\n if ({?'rt'} is null)\n {\n tmp := OAUTH..get_session_data (sid);\n pars := get_keyword ('pars', tmp, pars);\n meth := get_keyword ('meth', tmp, meth);\n }\n url := sprintf ('http://localhost:%s/ods/api/%s', server_http_port (), meth);\n tmp := split_and_decode (pars);\n params := '';\n for (declare i,l int, l:=length (tmp); i < l; i := i + 2)\n {\n params := params || sprintf ('%U=%U&', tmp[i], tmp[i+1]);\n }\n --params := sprintf ('inst_id=%d&description=%U&title=%U', 15, 'Some test post', 'testing');\n consumer_key := OAUTH..get_consumer_key (sid);\n url := OAUTH..sign_request ('GET', url, params, consumer_key, sid);\n res := http_get (url);\n --dbg_obj_print (res);\n }\n?>\n <head><title>OAuth Client</title></head>\n <body>\n <h1>OAuth client for ODS Controllers</h1>\n <form method=\"POST\" action=\"oauth_client.vsp\">\n <input type=\"hidden\" name=\"sid\" value=\"<?V sid ?>\"/>\n APPLICATION : <br/> <select name=\"key\">\n <?vsp for select a_name, a_key from OAUTH..APP_REG do { ?>\n <option value=\"<?V a_key ?>\" <?vsp if (consumer_key = a_key) http ('selected'); ?>><?V a_name ?></option>\n <?vsp } ?>\n </select>\n <?vsp\n if (sid is not null) http (sprintf (' TOKEN: %s', OAUTH..get_auth_token (sid)));\n ?>\n <br/>\n ODS API: <br/><input type=\"text\" name=\"meth\" value=\"<?V meth ?>\" size=50/> <br/>\n PARAMETERS: <br/> <textarea name=\"pars\" rows=\"5\" cols=\"50\"><?V pars ?></textarea> <br/>\n <input type=\"submit\" value=\"Execute\" name=\"rt\"/><br/>\n </form>\n RESULT:\n <hr/>\n <pre><?V res ?></pre>\n </body>\n</html>\n\n\nThe following is a sample session recorded with the client above :\n\n\nGET /OAuth/request_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b8333607ed\nc5f36&oauth_nonce=b8f1089077cbce6e&oauth_signature_method=HMAC-SHA1&oauth_times\ntamp=1211212829&oauth_version=1.0&oauth_signature=V1zmk757LBHcmqVJ6obMhNX5hKA%3\nD HTTP/1.1\nHost: localhost:8890\n\nHTTP/1.1 200 Ok\nContent-Length: NNN\n<CR/LF>\noauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth_token_secret=M...\n\n\n\n\nGET /OAuth/authorize?oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth\n_callback=http%3A//localhost%3A8890/oauth/oauth_client.vsp%3Fready%3D00c874b2fa\nb2f6424008b5064fe83e88 HTTP/1.1\nHost: localhost:8890\n\nHTTP/1.1 301 Moved\nLocation: /ods/oauth_authorize.vspx?....\n\n\n\n\nGET /OAuth/access_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b8333607edc\n5f36&oauth_nonce=242cc4875a0059f6&oauth_signature_method=HMAC-SHA1&oauth_timest\namp=1211212831&oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth_versi\non=1.0&oauth_signature=sqs/8nmNNnNJiZ/eBa688uNeg9o%3D HTTP/1.1\nHost: localhost:8890\n\nHTTP/1.1 200 Ok\nContent-Length: NNN\n<CR/LF>\noauth_token=N..&oauth_token_secret=M...\n\n\n\nGET /ods/api/weblog.post.new?description=Some%20test%20post&inst_id=15&oauth_co\nnsumer_key=50082d0fb861b0e6e67d5d986b8333607edc5f36&oauth_nonce=2f4765d20664e69\n6&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1211213321&oauth_token=db83a\n37d74faf53edc8ed56d418ded3a70fcc0bc&oauth_version=1.0&title=testing&oauth_signa\nture=oocIyr6kgoEQkC3WVwzvl6w62W4%3D HTTP/1.1\nHost: localhost:8890\n\n\nHTTP/1.1 200 Ok\nContent-Length: NNN\n<CR/LF>\n<result><code>1</code></result>\n\n\n---+++ Session based\n\nThe request to the API in this type of authentication must have 'sid' & 'realm'\nvia 'user.authenticate' method:\n\nTo get session id:\n\ncurl -i \"http://localhost:8890/ods/api/user.authenticate?user_name=demo&passwor\nd_hash=fe1774cfea9f7b402796751a4616c04a6f010ecb\"\nHTTP/1.1 200 OK\nContent-Type: text/plain; charset=\"UTF-8\"\nContent-Length: 32\n\nbfb2b13e4218a99f65b956eb6ba657cb << SID\n\n\n\nPerform weblog.post.new API call:\n\ncurl -i \"http://localhost:8890/ods/api/weblog.post.new?title=test&description=S\nome%20test%20post&inst_id=15&sid=bfb2b13e4218a99f65b956eb6ba657cb&realm=wa\"\nHTTP/1.1 200 OK\nConnection: Keep-Alive\nContent-Type: text/xml; charset=\"UTF-8\"\nContent-Length: 53\n<CR/LF>\n<result><code>1</code></result>\n\n\n---+++ password hash\n\nThis approach is similar to above, but instead of sid and realm we just pass as\nparameters to request the user_name & password_hash .\n\n---++ Response format\n\n---+++ IUD operations\n\nThe IUD methods return an XML response with code & message format follows:\n\n---++++ On success\n\n<result><code>NNN</code><message>human readable explanation if applicable</message></result>\n\n---++++ On failure\n\n<failed><code>NNN</code><failed>human readable explanation</message></failed>\n\n---+++ Search (get)\n\nThe search methods returns results in RDF format according to FOAF, SIOC and SIOC\ntypes module ontology. See ODS RDF model.\n\n---++ API methods\n\nAll APIs are acting on behalf of the user who established authentication, i.e.,\nthe user which is authorized. The APIs where user is subject of removal or freeze\nas well as registration the user name is passed as parameter. Therefore user.register,\nuser.delete would need user name as input parameter where user.update, instance.create\nwill use the user from authentication information.\n\n---+++ Framework\n\n\nuser.register (\n name varchar,\n password varchar,\n email varchar\n )\nuser.authenticate (\n user_name varchar,\n password_hash varchar\n )\nuser.update (user_info any)\nuser.password_change (new_password varchar)\nuser.delete (name varchar)\nuser.enable (name varchar)\nuser.disable (name varchar)\nuser.get (name varchar)\nuser.search (pattern varchar)\nuser.invite (\n friends_email varchar,\n custom_message varchar default ''\n )\nuser.invitation (\n invitation_id varchar,\n approve int\n )\nuser.invitations.get ()\nuser.relation_terminate (friend varchar)\nuser.tagging_rules.add (\n rulelist_name varchar,\n rules any,\n is_public int default 1\n )\nuser.tagging_rules.delete (rulelist_name varchar)\nuser.tagging_rules.update (\n rulelist_name varchar,\n rules any\n )\nuser.hyperlinking_rules.add (rules any)\nuser.hyperlinking_rules.update (rules any)\nuser.hyperlinking_rules.delete (rules any)\nuser.annotation.add (\n claimIri varchar,\n claimRelation varchar,\n claimValue varchar\n )\nuser.annotation.delete (\n claimIri varchar,\n claimRelation varchar,\n claimValue varchar\n )\n\ninstance.create (\n type varchar,\n name varchar,\n description varchar,\n model int,\n public int\n )\ninstance.update (\n inst_id int,\n name varchar,\n description varchar,\n model int,\n public int\n )\ninstance.delete (inst_id int)\ninstance.freeze (name varchar)\ninstance.unfreeze (name varchar)\ninstance.join (inst_id int)\ninstance.disjoin (inst_id int)\ninstance.join_approve (\n inst_id int,\n uname varchar\n )\ninstance.notification.services ()\ninstance.notification.set (\n inst_id int,\n services any\n )\ninstance.notification.cancel (\n inst_id int,\n services any\n )\ninstance.notification.log (inst_id int)\ninstance.get (inst_id int)\ninstance.get.id (name varchar)\n\nsite.search (\n pattern varchar,\n options any\n )\n\n\n---+++ Briefcase\n * [[VirtuosoOdsControllersBriefcase][Briefcase Controllers]]\n\n---+++ Weblog\n * [[VirtuosoOdsControllersWeblog][Weblog Controllers]]\n * [[OdsWeblogProgrammersGuide][Weblog's Programmers Guide]]\n\n---+++ Addressbook\n * [[VirtuosoOdsControllersAddressbook][Addressbook Controllers]]\n * [[OdsAddressbookProgrammersGuide][Addressbook's Programmers Guide]]\n\n---+++ Bookmarks\n * [[VirtuosoOdsControllersBookmarks][Bookmarks Controllers]]\n * [[OdsBookmarkManager][Bookmarks Programmers Guide]]\n\n---+++ Polls\n * [[VirtuosoOdsControllersPolls][Polls Controllers]]\n * [[OdsPollsProgrammersGuide][Poll's Programmers Guide]]\n\n\n---+++ Calendar\n * [[VirtuosoOdsControllersCalendar][Calendar Controllers]]\n * [[OdsCalendarProgrammersGuide][Calendar's Programmers Guide]]\n\n---+++ Feed Manager\n * [[VirtuosoOdsControllersFeeds][Feed Manager Controllers]]\n * [[OdsFeedManagerProgrammersGuide][Feed Manager's Programmers Guide]]\n\n---+++ Webmail\n * [[VirtuosoOdsControllersWebmail][Webmail Controllers]]\n * [[OdsWebmailProgrammersGuide][Webmail's Programmers Guide]]\n\n---+++ Discussion\n * [[VirtuosoOdsControllersDiscussion][Discussion Controllers]]\n * [[OdsDiscussionsProgrammersGuide][Discussions 's Programmers Guide]]\n\n---+++ Gallery\n * [[VirtuosoOdsControllersGallery][Gallery Controllers]]\n\n---+++ Wiki\n * [[VirtuosoOdsControllersWiki][Wiki Controllers]]\n\n---+++ Messenger\n * [[VirtuosoOdsControllersMessenger][Messenger Controllers]]\n\n---++References\n\n * [[OAuth][OpenLink's explanation of OAuth]]\n * [[VirtuosoOAuthServer][Virtuoso OAuth server]]\n * [[VirtOAuthControllers][Using OAuth with ODS]]\n * [[VirtuosoOdsUbiquity][ODS Ubiquity Commands]]\n * [[VirtOAuth][Virtuoso OAuth Implementation]]\n * [[VirtODSOAuthQA][Testing Virtuoso OAuth with 3rd Party OAuth Clients]]\n * [[VirtuosoOdsUbiquityTutorialsOAuth][OAuth Ubiquity Tutorial]]\n * [[VirtOAuthTestTool][Virtuoso OAuth Test Tool for ODS Controllers]]\n * [[VirtOAuthSPARQL][Virtuoso SPARQL OAuth Tutorial]]\n * [[VirtuosoOdsUbiquityTutorials][ODS Ubiquity Tutorials]]\n * [[VirtOAuthExamples][OAuth Applications Authentication examples]]\n * [[http://oauth.net/core/1.0/][OAuth API]]\n\n\n\nCategoryODS CategoryVirtuoso " . . .