From e24815bd72e55fa6550f40553ee94ea2a3f40d1d Mon Sep 17 00:00:00 2001 From: Stuart Clark Date: Tue, 20 Jan 2015 10:01:42 +1100 Subject: [PATCH 1/4] Update Locale:: to AppLocale:: --- RestPlugin.inc.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/RestPlugin.inc.php b/RestPlugin.inc.php index 7aa705b..f905d1e 100644 --- a/RestPlugin.inc.php +++ b/RestPlugin.inc.php @@ -48,11 +48,11 @@ function getName() { } function getDisplayName() { - return Locale::translate('plugins.gateways.rest.displayName'); + return AppLocale::translate('plugins.gateways.rest.displayName'); } function getDescription() { - return Locale::translate('plugins.gateways.rest.description'); + return AppLocale::translate('plugins.gateways.rest.description'); } /** @@ -69,7 +69,7 @@ function fetch($args, &$request) { if (!isset($journal)) $this->showError(); $issueDao =& DAORegistry::getDAO('IssueDAO'); - + $journalId = $journal->getId(); $operator = array_shift($args); @@ -98,28 +98,28 @@ function fetch($args, &$request) { $response = $this->_getIssueInfo($request, $journalId, $issue); echo json_encode($response); - break; + break; case 'issueDataWithArticles': //Issue metadata along with all included article metadata // Takes issue ID as input $issueId = (int) array_shift($args); - + $issue =& $issueDao->getIssueById($issueId, $journalId); - + $response = $this->_getIssueInfo($request, $journalId, $issue, true); echo json_encode($response); break; case 'currentIssueData': // Current issue metadata $issue =& $issueDao->getCurrentIssue($journalId, true); - + $response = $this->_getIssueInfo($request, $journalId, $issue); echo json_encode($response); break; case 'currentIssueDataWithArticles': // Current issue metadata along with all included article metadata $issue =& $issueDao->getCurrentIssue($journalId, true); - + $response = $this->_getIssueInfo($request, $journalId, $issue, true); echo json_encode($response); - break; + break; case 'allIssueData': // Metadata for all published issues $issues =& $issueDao->getPublishedIssues($journalId); @@ -170,7 +170,7 @@ function fetch($args, &$request) { */ function showError() { header("HTTP/1.0 500 Internal Server Error"); - echo Locale::translate('plugins.gateways.rest.errors.errorMessage'); + echo AppLocale::translate('plugins.gateways.rest.errors.errorMessage'); exit; } @@ -184,15 +184,15 @@ function showError() { function _getIssueInfo(&$request, $journalId, $issue, $withArticles = false) { if(!isset($issue)) $this->showError(); - Locale::requireComponents(array(LOCALE_COMPONENT_APPLICATION_COMMON)); - + AppLocale::requireComponents(array(LOCALE_COMPONENT_APPLICATION_COMMON)); + //Handle getting the image URL $publicFileManager = new PublicFileManager(); $coverPagePath = $request->getBaseUrl() . '/'; $coverPagePath .= $publicFileManager->getJournalFilesPath($journalId) . '/'; $imageFileName = $issue->getIssueFileName(); $imageUrl = $coverPagePath . $imageFileName; - + $response = array( 'url' => $request->url(null, 'issue', 'view', $issue->getId()), 'issueId' => $issue->getId(), @@ -217,7 +217,7 @@ function _getIssueInfo(&$request, $journalId, $issue, $withArticles = false) { } $response['articles'] = $articles; } - + return $response; } @@ -267,7 +267,7 @@ function _getArticleInfo(&$request, $articleId) { 'sectionId' => $article->getSectionId(), 'sectionTitle' => $article->getSectionTitle() ); - + $articleGalleyDAO =& DAORegistry::getDAO('ArticleGalleyDAO'); $articleGalleys =& $articleGalleyDAO->getGalleysByArticle($articleId); $galleysResponse = array(); @@ -281,7 +281,7 @@ function _getArticleInfo(&$request, $articleId) { $galleysResponse[] = $galleyInfo; } $response['galleys'] = $galleysResponse; - + // Add some optional metadata. There may be other items the could be included here. if($article->getLocalizedDiscipline()) $response['discipline'] = $article->getLocalizedDiscipline(); if($article->getLocalizedSubjectClass()) $response['subjectClass'] = $article->getLocalizedSubjectClass(); @@ -295,4 +295,4 @@ function _getArticleInfo(&$request, $articleId) { } } -?> \ No newline at end of file +?> From 2e37065e700678966d08a6add51e20189c8b1f18 Mon Sep 17 00:00:00 2001 From: Stuart Clark Date: Tue, 20 Jan 2015 11:32:56 +1100 Subject: [PATCH 2/4] Added API Key authentication and settings --- README | 14 +++++--- RestPlugin.inc.php | 52 +++++++++++++++++++++++++++-- SettingsForm.inc.php | 72 +++++++++++++++++++++++++++++++++++++++++ locale/en_US/locale.xml | 4 ++- settingsForm.tpl | 36 +++++++++++++++++++++ 5 files changed, 169 insertions(+), 9 deletions(-) create mode 100644 SettingsForm.inc.php create mode 100644 settingsForm.tpl diff --git a/README b/README index bcddb33..f31d809 100644 --- a/README +++ b/README @@ -5,17 +5,22 @@ The REST gateway plugin gets information on a journal in JSON format via HTTP. It can be addressed with the following URL pattern: -http://localhost/ojs2/index.php/myJournal/gateway/plugin/RestPlugin/... +http://localhost/ojs2/index.php/myJournal/gateway/plugin/RestPlugin/...?apiKey=APIKEY ...where, of course, localhost is the local server name, ojs2 is the path -to the OJS 2.x installation, and myJournal is the path to a particular -journal. +to the OJS 2.x installation, myJournal is the path to a particular +journal, and APIKEY is your unique API key. The plugin must be enabled in order to respond to requests. To enable the plugin, or ensure that it is sufficiently configured, log into the Journal Manager's "System Plugins" page, find the REST Plugin under the "Gateway Plugins" page, and click "Enable". +Once enabled, an API Key is generated (which can be changed) that is needed +to authenticate all requests. To get or change the API Key, log into the +Journal Manager's "System Plugins" page, find the REST Plugin under the +"Gateway Plugins" page, and click "Settings". + The plugin has the following methods to request data: http://.../RestPlugin/journalInfo -- Get general info about a journal. @@ -29,7 +34,6 @@ http://.../RestPlugin/allIssueDataWithArticles -- Get metadata for all issues, a http://.../RestPlugin/announcements -- Retrieve all announcements in chronological order TODO: - -API Key (Only allow access from registered agents) -User authentication to get user data -XML result sets (only returns JSON for now) - -More methods into the system, beefier API, as well as better API documentation \ No newline at end of file + -More methods into the system, beefier API, as well as better API documentation diff --git a/RestPlugin.inc.php b/RestPlugin.inc.php index f905d1e..38ce6c6 100644 --- a/RestPlugin.inc.php +++ b/RestPlugin.inc.php @@ -15,6 +15,7 @@ import('classes.plugins.GatewayPlugin'); import('classes.file.PublicFileManager'); +import('classes.user.UserDAO'); class RestPlugin extends GatewayPlugin { /** @@ -55,7 +56,43 @@ function getDescription() { return AppLocale::translate('plugins.gateways.rest.description'); } - /** + function getManagementVerbs() { + $verbs = parent::getManagementVerbs(); + if (!$this->getEnabled()) return $verbs; + $verbs[] = array( + 'settings', __('plugins.gateways.metsGateway.settings') + ); + return $verbs; + } + + function manage($verb, $args) { + if (parent::manage($verb, $args)) return true; + if (!$this->getEnabled()) return false; + switch ($verb) { + case 'settings': + $journal =& Request::getJournal(); + $this->import('SettingsForm'); + $form = new SettingsForm($this, $journal->getId()); + if (Request::getUserVar('save')) { + $form->readInputData(); + if ($form->validate()) { + $form->execute(); + Request::redirect(null, null, 'plugins'); + } else { + $form->display(); + } + } else { + $form->initData(); + $form->display(); + } + break; + default: + return false; + } + return true; + } + + /** * Handle fetch requests for this plugin. * @param $args array * @param $request PKPRequest @@ -68,10 +105,19 @@ function fetch($args, &$request) { $journal =& $request->getJournal(); if (!isset($journal)) $this->showError(); - $issueDao =& DAORegistry::getDAO('IssueDAO'); - $journalId = $journal->getId(); + // Check request is authenticated via API Key. + $apiKey = $request->getUserVar('apiKey'); + if (is_null($apiKey) || $apiKey != $this->getSetting($journalId, 'apiKey')) { + return false; + } + + // Ensure user is authenticated. + $user = new UserDAO(); + + $issueDao =& DAORegistry::getDAO('IssueDAO'); + $operator = array_shift($args); switch ($operator) { case 'journalInfo': // Basic journal metadata diff --git a/SettingsForm.inc.php b/SettingsForm.inc.php new file mode 100644 index 0000000..4650713 --- /dev/null +++ b/SettingsForm.inc.php @@ -0,0 +1,72 @@ +journalId = $journalId; + $this->plugin =& $plugin; + + parent::Form($plugin->getTemplatePath() . 'settingsForm.tpl'); + $this->addCheck(new FormValidatorPost($this)); + } + + /** + * Initialize form data. + */ + function initData() { + $journalId = $this->journalId; + $plugin =& $this->plugin; + + if ($plugin->getSetting($journalId, 'apiKey') == '') { + $this->setData('apiKey', Validation::generatePassword(16)); + $plugin->updateSetting($journalId, 'apiKey', $this->getData('apiKey')); + } else { + $this->setData('apiKey', $plugin->getSetting($journalId, 'apiKey')); + } + } + + /** + * Assign form data to user-submitted data. + */ + function readInputData() { + $this->readUserVars(array('apiKey')); + } + + /** + * Save settings. + */ + function execute() { + $plugin =& $this->plugin; + $journalId = $this->journalId; + + $plugin->updateSetting($journalId, 'apiKey', $this->getData('apiKey')); + } + +} + +?> diff --git a/locale/en_US/locale.xml b/locale/en_US/locale.xml index ccde42a..ab59c69 100644 --- a/locale/en_US/locale.xml +++ b/locale/en_US/locale.xml @@ -11,9 +11,11 @@ * * $Id$ --> - + REST API Plugin This plugin allows external sources to query this journal for information, returned to the source in JSON format. Unable to parse request. + Settings + API Key diff --git a/settingsForm.tpl b/settingsForm.tpl new file mode 100644 index 0000000..4655893 --- /dev/null +++ b/settingsForm.tpl @@ -0,0 +1,36 @@ +{** + * plugins/gateways/rest/settingsForm.tpl + * + * Copyright (c) 2003-2011 John Willinsky + * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. + * + * OJS REST gateway plugin settings + * + *} +{strip} +{assign var="pageTitle" value="plugins.gateways.rest.displayName"} +{include file="common/header.tpl"} +{/strip} + +{url|assign:"directoryUrl" page="gateway" op="plugin" path="RestPlugin"} +
+

{translate key="plugins.gateways.rest.settings"}

+ +
+{include file="common/formErrors.tpl"} + + + + + + +
{fieldLabel name="apiKey" key="plugins.gateways.rest.settings.apiKey"} +
+ +
+ + + +
+
+{include file="common/footer.tpl"} From 07d77a6c1548b536d9caf95bde1ea64943ae522f Mon Sep 17 00:00:00 2001 From: Stuart Clark Date: Tue, 20 Jan 2015 12:43:11 +1100 Subject: [PATCH 3/4] Added userAdd method. --- README | 1 + RestPlugin.inc.php | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/README b/README index f31d809..9c504a1 100644 --- a/README +++ b/README @@ -32,6 +32,7 @@ http://.../RestPlugin/currentIssueDataWithArticles -- Get metadata for the curre http://.../RestPlugin/allIssueData -- Get metadata for all issues. If the additional parameter is set to 1, all articles will be included. http://.../RestPlugin/allIssueDataWithArticles -- Get metadata for all issues, along with all their articles. http://.../RestPlugin/announcements -- Retrieve all announcements in chronological order +http://.../RestPlugin/userAdd -- Add a user. TODO: -User authentication to get user data diff --git a/RestPlugin.inc.php b/RestPlugin.inc.php index 38ce6c6..c267974 100644 --- a/RestPlugin.inc.php +++ b/RestPlugin.inc.php @@ -108,13 +108,11 @@ function fetch($args, &$request) { $journalId = $journal->getId(); // Check request is authenticated via API Key. - $apiKey = $request->getUserVar('apiKey'); - if (is_null($apiKey) || $apiKey != $this->getSetting($journalId, 'apiKey')) { + $requestData = $request->getUserVars(); + if (is_null($requestData['apiKey']) || $requestData['apiKey'] != $this->getSetting($journalId, 'apiKey')) { return false; } - - // Ensure user is authenticated. - $user = new UserDAO(); + unset($requestData['apiKey']); $issueDao =& DAORegistry::getDAO('IssueDAO'); @@ -204,6 +202,18 @@ function fetch($args, &$request) { echo json_encode($response); break; + case 'userAdd': + $user = new User(); + foreach ($requestData as $key => $value) { + $user->setData($key, $value); + } + $userDao =& DAORegistry::getDAO('UserDAO'); + if (!$userDao->insertUser($user)) { + return false; + } + + echo json_encode($user); + break; default: // Not a valid request $this->showError(); From f58aec6599fda3cf68bfac3c55e5e62582686364 Mon Sep 17 00:00:00 2001 From: Stuart Clark Date: Tue, 20 Jan 2015 14:52:21 +1100 Subject: [PATCH 4/4] Added enrollUser method. --- README | 1 + RestPlugin.inc.php | 40 +++++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/README b/README index 9c504a1..4527fda 100644 --- a/README +++ b/README @@ -33,6 +33,7 @@ http://.../RestPlugin/allIssueData -- Get metadata for all issues. If the addit http://.../RestPlugin/allIssueDataWithArticles -- Get metadata for all issues, along with all their articles. http://.../RestPlugin/announcements -- Retrieve all announcements in chronological order http://.../RestPlugin/userAdd -- Add a user. +http://.../RestPlugin/userEnroll -- Enroll specified user to specified roll. TODO: -User authentication to get user data diff --git a/RestPlugin.inc.php b/RestPlugin.inc.php index c267974..4615974 100644 --- a/RestPlugin.inc.php +++ b/RestPlugin.inc.php @@ -26,6 +26,7 @@ class RestPlugin extends GatewayPlugin { */ function register($category, $path) { $success = parent::register($category, $path); + HookRegistry::register ('Request::redirect', array(&$this, 'preventRedirect')); $this->addLocaleData(); return $success; } @@ -110,12 +111,13 @@ function fetch($args, &$request) { // Check request is authenticated via API Key. $requestData = $request->getUserVars(); if (is_null($requestData['apiKey']) || $requestData['apiKey'] != $this->getSetting($journalId, 'apiKey')) { - return false; + $this->showError(); } unset($requestData['apiKey']); $issueDao =& DAORegistry::getDAO('IssueDAO'); + $response = FALSE; $operator = array_shift($args); switch ($operator) { case 'journalInfo': // Basic journal metadata @@ -126,14 +128,11 @@ function fetch($args, &$request) { 'initials' => $journal->getLocalizedInitials(), 'description' => $journal->getLocalizedDescription(), ); - - echo json_encode($response); break; case 'articleInfo': // Article metadata // Takes article ID as input $articleId = (int) array_shift($args); $response = $this->_getArticleInfo($request, $articleId); - echo json_encode($response); break; case 'issueData': // Issue metadata //Takes article ID as input @@ -141,7 +140,6 @@ function fetch($args, &$request) { $issue =& $issueDao->getIssueById($issueId, $journalId); $response = $this->_getIssueInfo($request, $journalId, $issue); - echo json_encode($response); break; case 'issueDataWithArticles': //Issue metadata along with all included article metadata // Takes issue ID as input @@ -150,19 +148,16 @@ function fetch($args, &$request) { $issue =& $issueDao->getIssueById($issueId, $journalId); $response = $this->_getIssueInfo($request, $journalId, $issue, true); - echo json_encode($response); break; case 'currentIssueData': // Current issue metadata $issue =& $issueDao->getCurrentIssue($journalId, true); $response = $this->_getIssueInfo($request, $journalId, $issue); - echo json_encode($response); break; case 'currentIssueDataWithArticles': // Current issue metadata along with all included article metadata $issue =& $issueDao->getCurrentIssue($journalId, true); $response = $this->_getIssueInfo($request, $journalId, $issue, true); - echo json_encode($response); break; case 'allIssueData': // Metadata for all published issues $issues =& $issueDao->getPublishedIssues($journalId); @@ -172,7 +167,6 @@ function fetch($args, &$request) { $response[] = $this->_getIssueInfo($request, $journalId, $issue); unset($issue); } - echo json_encode($response); break; case 'allIssueDataWithArticles': // Metadata for all published issues and all their articles (can be big!) $issues =& $issueDao->getPublishedIssues($journalId); @@ -182,7 +176,6 @@ function fetch($args, &$request) { $response[] = $this->_getIssueInfo($request, $journalId, $issue, true); unset($issue); } - echo json_encode($response); break; case 'announcements': // Announcements $announcementDao =& DAORegistry::getDAO('AnnouncementDAO'); @@ -199,8 +192,6 @@ function fetch($args, &$request) { ); unset($announcement); } - - echo json_encode($response); break; case 'userAdd': $user = new User(); @@ -211,13 +202,24 @@ function fetch($args, &$request) { if (!$userDao->insertUser($user)) { return false; } - - echo json_encode($user); + $response = $user; break; - default: - // Not a valid request - $this->showError(); + case 'userEnroll': + if (isset($requestData['userId']) && isset($requestData['roleId'])) { + import('pages.manager.PeopleHandler'); + $handler = new PeopleHandler($request); + $handler->_checks = array(); + $handler->enroll($args); + + $roleDao =& DAORegistry::getDAO('RoleDAO'); + $response = $roleDao->userHasRole($journalId, $requestData['userId'], $requestData['roleId']); + } + break; + } + if (!$response) { + $this->showError(); } + echo json_encode($response); return true; } @@ -349,6 +351,10 @@ function _getArticleInfo(&$request, $articleId) { return $response; } + + function preventRedirect($url) { + return TRUE; + } } ?>