diff --git a/README b/README index bcddb33..4527fda 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. @@ -27,9 +32,10 @@ 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. +http://.../RestPlugin/userEnroll -- Enroll specified user to specified roll. 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 7aa705b..4615974 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 { /** @@ -25,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; } @@ -48,14 +50,50 @@ 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'); } - /** + 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 +106,18 @@ 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. + $requestData = $request->getUserVars(); + if (is_null($requestData['apiKey']) || $requestData['apiKey'] != $this->getSetting($journalId, 'apiKey')) { + $this->showError(); + } + unset($requestData['apiKey']); + + $issueDao =& DAORegistry::getDAO('IssueDAO'); + + $response = FALSE; $operator = array_shift($args); switch ($operator) { case 'journalInfo': // Basic journal metadata @@ -82,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 @@ -97,29 +140,25 @@ function fetch($args, &$request) { $issue =& $issueDao->getIssueById($issueId, $journalId); $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); @@ -128,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); @@ -138,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'); @@ -155,13 +192,34 @@ function fetch($args, &$request) { ); unset($announcement); } + 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; + } + $response = $user; + break; + case 'userEnroll': + if (isset($requestData['userId']) && isset($requestData['roleId'])) { + import('pages.manager.PeopleHandler'); + $handler = new PeopleHandler($request); + $handler->_checks = array(); + $handler->enroll($args); - echo json_encode($response); + $roleDao =& DAORegistry::getDAO('RoleDAO'); + $response = $roleDao->userHasRole($journalId, $requestData['userId'], $requestData['roleId']); + } break; - default: - // Not a valid request - $this->showError(); } + if (!$response) { + $this->showError(); + } + echo json_encode($response); return true; } @@ -170,7 +228,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 +242,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 +275,7 @@ function _getIssueInfo(&$request, $journalId, $issue, $withArticles = false) { } $response['articles'] = $articles; } - + return $response; } @@ -267,7 +325,7 @@ function _getArticleInfo(&$request, $articleId) { 'sectionId' => $article->getSectionId(), 'sectionTitle' => $article->getSectionTitle() ); - + $articleGalleyDAO =& DAORegistry::getDAO('ArticleGalleyDAO'); $articleGalleys =& $articleGalleyDAO->getGalleysByArticle($articleId); $galleysResponse = array(); @@ -281,7 +339,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(); @@ -293,6 +351,10 @@ function _getArticleInfo(&$request, $articleId) { return $response; } + + function preventRedirect($url) { + return TRUE; + } } -?> \ No newline at end of file +?> 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"}