Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
asmecher committed Jun 14, 2014
1 parent 27f3e37 commit 864b307
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 0 deletions.
201 changes: 201 additions & 0 deletions SubscriptionSSOPlugin.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<?php

/**
* @file plugins/generic/subscriptionSSO/SubscriptionSSOPlugin.inc.php
*
* Copyright (c) 2014 Simon Fraser University Library
* Copyright (c) 2014 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file COPYING.
*
* @package plugins_generic_subscriptionSSO
*
* Plugin to defer subscription checks to an external system.
*
*/

import('classes.plugins.GenericPlugin');

class SubscriptionSSOPlugin extends GenericPlugin {
/**
* @copydoc GenericPlugin::register
*/
function register($category, $path) {
$success = parent::register($category, $path);
if (!Config::getVar('general', 'installed') || defined('RUNNING_UPGRADE')) return true;
if ($success && $this->getEnabled()) {
$this->addLocaleData();
HookRegistry::register('LoadHandler',array(&$this, 'loadHandlerCallback'));
HookRegistry::register('IssueAction::subscribedUser', array(&$this, 'subscribedUserCallback'));
return true;
}
return $success;
}

/**
* Callback when a handler is loaded. Used to check for the presence
* of an incoming authentication, which needs to be verified.
* @param $hookName string Hook name
* @param $args array Hook arguments
* @return boolean Hook return status
*/
function loadHandlerCallback($hookName, $args) {
$journal = Request::getJournal();
$incomingParameterName = $this->getSetting($journal->getId(), 'incomingParameterName');
// Using $_GET rather than Request because this may be case
// sensitive (e.g. differentiating myid from myId)
if ($incomingParameterName != '' && isset($_GET[$incomingParameterName])) {
$incomingKey = $_GET[$incomingParameterName];

// This is an incoming authorization. Contact the remote service.
$verificationUrl = $this->getSetting($journal->getId(), 'verificationUrl');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $verificationUrl . urlencode($incomingKey));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
curl_close($ch);

// Verify the result.
$resultRegexp = $this->getSetting($journal->getId(), 'resultRegexp');
if (preg_match($resultRegexp, $result)) {
// Successfully validated.
$_SESSION['subscriptionSSOTimestamp'] = time();
} else {
// Failed to validate.
unset($_SESSION['subscriptionSSOTimestamp']);
Request::redirectURL($this->getSetting($journal->getId(), 'redirectUrl'));
}
}
return false;
}

/**
* Callback when a handler is loaded. Used to check for the presence
* of an incoming authentication, which needs to be verified.
* @param $hookName string Hook name
* @param $args array Hook arguments
* @return boolean Hook return status
*/
function subscribedUserCallback($hookName, $args) {
$journal =& $args[0];
$result =& $args[1]; // Reference required
$result = isset($_SESSION['subscriptionSSOTimestamp']) && $_SESSION['subscriptionSSOTimestamp'] + ($this->getSetting($journal->getId(), 'hoursValid') * 3600) < time();
}

/**
* Extend the {url ...} smarty to support this plugin.
* @param $params array
* @param $smarty Smarty
*/
function smartyPluginUrl($params, &$smarty) {
$path = array($this->getCategory(), $this->getName());
if (is_array($params['path'])) {
$params['path'] = array_merge($path, $params['path']);
} elseif (!empty($params['path'])) {
$params['path'] = array_merge($path, array($params['path']));
} else {
$params['path'] = $path;
}

if (!empty($params['id'])) {
$params['path'] = array_merge($params['path'], array($params['id']));
unset($params['id']);
}
return $smarty->smartyUrl($params, $smarty);
}

/**
* Set the page's breadcrumbs, given the plugin's tree of items
* to append.
* @param $subclass boolean
*/
function setBreadcrumbs($isSubclass = false) {
$templateMgr =& TemplateManager::getManager();
$pageCrumbs = array(
array(
Request::url(null, 'user'),
'navigation.user'
),
array(
Request::url(null, 'manager'),
'user.role.manager'
)
);
if ($isSubclass) $pageCrumbs[] = array(
Request::url(null, 'manager', 'plugins'),
'manager.plugins'
);

$templateMgr->assign('pageHierarchy', $pageCrumbs);
}

/**
* Display verbs for the management interface.
* @return array
*/
function getManagementVerbs() {
$verbs = array();
if ($this->getEnabled()) {
$verbs[] = array('settings', __('plugins.generic.subscriptionSSO.settings'));
}
return parent::getManagementVerbs($verbs);
}

/**
* Execute a management verb on this plugin
* @param $verb string
* @param $args array
* @param $message string Result status message
* @param $messageParams array Parameters for the message key
* @return boolean
*/
function manage($verb, $args, &$message, &$messageParams) {
if (!parent::manage($verb, $args, $message, $messageParams)) return false;

switch ($verb) {
case 'settings':
$templateMgr =& TemplateManager::getManager();
$templateMgr->register_function('plugin_url', array(&$this, 'smartyPluginUrl'));
$journal =& Request::getJournal();

$this->import('SubscriptionSSOSettingsForm');
$form = new SubscriptionSSOSettingsForm($this, $journal->getId());
if (Request::getUserVar('save')) {
$form->readInputData();
if ($form->validate()) {
$form->execute();
Request::redirect(null, 'manager', 'plugin');
return false;
} else {
$this->setBreadcrumbs(true);
$form->display();
}
} else {
$this->setBreadcrumbs(true);
$form->initData();
$form->display();
}
return true;
default:
// Unknown management verb
assert(false);
return false;
}
}

/**
* @copydoc Plugin::getDisplayName
*/
function getDisplayName() {
return __('plugins.generic.subscriptionSSO.name');
}

/**
* @copydoc Plugin::getDescription
*/
function getDescription() {
return __('plugins.generic.subscriptionSSO.description');
}
}

?>
84 changes: 84 additions & 0 deletions SubscriptionSSOSettingsForm.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

/**
* @file plugins/generic/subscriptionSSO/SubscriptionSSOSettingsForm.inc.php
*
* Copyright (c) 2014 Simon Fraser University Library
* Copyright (c) 2014 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file COPYING.
*
* @class SubscriptionSSOSettingsForm
* @ingroup plugins_generic_subscriptionSSO
*
* @brief Form for journal managers to modify subscription SSO plugin settings
*/


import('lib.pkp.classes.form.Form');

class SubscriptionSSOSettingsForm extends Form {

/** @var $journalId int */
var $journalId;

/** @var $plugin object */
var $plugin;

/**
* Constructor
* @param $plugin object
* @param $journalId int
*/
function SubscriptionSSOSettingsForm(&$plugin, $journalId) {
$this->journalId = $journalId;
$this->plugin =& $plugin;

parent::Form($plugin->getTemplatePath() . 'settingsForm.tpl');

$this->addCheck(new FormValidatorAlphaNum($this, 'incomingParameterName', 'required', 'plugins.generic.subscriptionSSO.settings.incomingParameterName.required'));
$this->addCheck(new FormValidatorURL($this, 'verificationUrl', 'required', 'plugins.generic.subscriptionSSO.settings.verificationUrl.required'));
$this->addCheck(new FormValidator($this, 'resultRegexp', 'required', 'plugins.generic.subscriptionSSO.settings.resultRegexp.required'));
$this->addCheck(new FormValidatorURL($this, 'redirectUrl', 'required', 'plugins.generic.subscriptionSSO.settings.redirectUrl.required'));
$this->addCheck(new FormValidatorURL($this, 'redirectUrl', 'required', 'plugins.generic.subscriptionSSO.settings.redirectUrl.required'));
$this->addCheck(new FormValidatorRegExp($this, 'hoursValid', 'required', 'plugins.generic.subscriptionSSO.settings.hoursValid.required', '/^[0-9]+$/'));
}

/**
* Initialize form data.
*/
function initData() {
$journalId = $this->journalId;
$plugin =& $this->plugin;

$this->_data = array(
'incomingParameterName' => $plugin->getSetting($journalId, 'incomingParameterName'),
'verificationUrl' => $plugin->getSetting($journalId, 'verificationUrl'),
'resultRegexp' => $plugin->getSetting($journalId, 'resultRegexp'),
'redirectUrl' => $plugin->getSetting($journalId, 'redirectUrl'),
'hoursValid' => $plugin->getSetting($journalId, 'hoursValid')
);
}

/**
* Assign form data to user-submitted data.
*/
function readInputData() {
$this->readUserVars(array('incomingParameterName', 'verificationUrl', 'resultRegexp', 'redirectUrl', 'hoursValid'));
}

/**
* Save settings.
*/
function execute() {
$plugin =& $this->plugin;
$journalId = $this->journalId;

$plugin->updateSetting($journalId, 'incomingParameterName', $this->getData('incomingParameterName'), 'string');
$plugin->updateSetting($journalId, 'verificationUrl', $this->getData('verificationUrl'), 'string');
$plugin->updateSetting($journalId, 'resultRegexp', $this->getData('resultRegexp'), 'string');
$plugin->updateSetting($journalId, 'redirectUrl', $this->getData('redirectUrl'), 'string');
$plugin->updateSetting($journalId, 'hoursValid', $this->getData('hoursValid'), 'string');
}
}

?>
23 changes: 23 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* @defgroup plugins_generic_subscriptionSSO
*/

/**
* @file plugins/generic/subscriptionSSO/index.php
*
* Copyright (c) 2014 Simon Fraser University Library
* Copyright (c) 2014 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file COPYING.
*
* @ingroup plugins_generic_subscriptionSSO
* @brief Wrapper for Subscription SSO plugin.
*
*/

require_once('SubscriptionSSOPlugin.inc.php');

return new SubscriptionSSOPlugin();

?>
30 changes: 30 additions & 0 deletions locale/en_US/locale.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE locale SYSTEM "../../../../../lib/pkp/dtd/locale.dtd">

<!--
* plugins/generic/subscriptionSSO/locale/en_US/locale.xml
*
* Copyright (c) 2014 Simon Fraser University Library
* Copyright (c) 2014 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file COPYING.
*
* Localization strings
-->

<locale name="en_US" full_name="U.S. English">
<message key="plugins.generic.subscriptionSSO.name">Subscription SSO Plugin</message>
<message key="plugins.generic.subscriptionSSO.description">This plugin delegates subscription checking to an external system for SSO (Single Sign On)-like behavior. When a request comes to OJS with the incoming parameter name specified -- this should be a parameter that OJS does not use internally -- the plugin will contact the verification URL with the value of the parameter appended. If the remove service's result matches the specified regular expression, the user will be considered valid. If not, the user will be redirected to the specified URL.</message>
<message key="plugins.generic.subscriptionSSO.settings">Settings</message>
<message key="plugins.generic.subscriptionSSO.subscriptionSSOSettings">Subscription Single Sign-On Settings</message>
<message key="plugins.generic.subscriptionSSO.settings.description">Use the following form to configure the external service that will provide confirmation of subscription status to OJS's subscription content.</message>
<message key="plugins.generic.subscriptionSSO.settings.incomingParameterName">Incoming parameter name</message>
<message key="plugins.generic.subscriptionSSO.settings.incomingParameterName.required">The incoming parameter name is required and must contain only alphanumeric characters.</message>
<message key="plugins.generic.subscriptionSSO.settings.verificationUrl">Verification URL</message>
<message key="plugins.generic.subscriptionSSO.settings.verificationUrl.required">The verification URL is required and must contain a valid URL.</message>
<message key="plugins.generic.subscriptionSSO.settings.resultRegexp">Verification Regular Expression</message>
<message key="plugins.generic.subscriptionSSO.settings.resultRegexp.required">The verification regular expression is a required field and must contain a valid regular expression.</message>
<message key="plugins.generic.subscriptionSSO.settings.redirectUrl">Redirect URL</message>
<message key="plugins.generic.subscriptionSSO.settings.redirectUrl.required">The redirect URL is required and must contain a valid URL.</message>
<message key="plugins.generic.subscriptionSSO.settings.hoursValid">Hours Valid</message>
<message key="plugins.generic.subscriptionSSO.settings.hoursValid.required">The maximum number of hours the session is valid must be an integer.</message>
</locale>
55 changes: 55 additions & 0 deletions settingsForm.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{**
* plugins/generic/subscriptionSSO/settingsForm.tpl
*
* Copyright (c) 2014 Simon Fraser University Library
* Copyright (c) 2014 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file COPYING.
*
* Subscription SSO plugin settings
*
*}
{strip}
{assign var="pageTitle" value="plugins.generic.subscriptionSSO.subscriptionSSOSettings"}
{include file="common/header.tpl"}
{/strip}
<div id="subscriptionSSOSettings">
<div id="description">{translate key="plugins.generic.subscriptionSSO.settings.description"}</div>

<div class="separator"></div>

<br />

<form method="post" action="{plugin_url path="settings"}">
{include file="common/formErrors.tpl"}

<table width="100%" class="data">
<tr valign="top">
<td width="40%" class="label">{fieldLabel name="incomingParameterName" required="true" key="plugins.generic.subscriptionSSO.settings.incomingParameterName"}</td>
<td width="60%" class="value"><input type="text" name="incomingParameterName" id="incomingParameterName" value="{$incomingParameterName|escape}" size="15" maxlength="25" class="textField" /></td>
</tr>
<tr valign="top">
<td class="label">{fieldLabel name="verificationUrl" required="true" key="plugins.generic.subscriptionSSO.settings.verificationUrl"}</td>
<td class="value"><input type="text" name="verificationUrl" id="verificationUrl" value="{$verificationUrl|escape}" size="40" maxlength="120" class="textField" /></td>
</tr>
<tr valign="top">
<td class="label">{fieldLabel name="resultRegexp" required="true" key="plugins.generic.subscriptionSSO.settings.resultRegexp"}</td>
<td class="value"><input type="text" name="resultRegexp" id="resultRegexp" value="{$resultRegexp|escape}" size="40" maxlength="120" class="textField" /></td>
</tr>
<tr valign="top">
<td class="label">{fieldLabel name="redirectUrl" required="true" key="plugins.generic.subscriptionSSO.settings.redirectUrl"}</td>
<td class="value"><input type="text" name="redirectUrl" id="redirectUrl" value="{$redirectUrl|escape}" size="40" maxlength="120" class="textField" /></td>
</tr>
<tr valign="top">
<td class="label">{fieldLabel name="hoursValid" required="true" key="plugins.generic.subscriptionSSO.settings.hoursValid"}</td>
<td class="value"><input type="text" name="hoursValid" id="hoursValid" value="{$hoursValid|escape}" size="15" maxlength="25" class="textField" /></td>
</tr>
</table>

<br/>

<input type="submit" name="save" class="button defaultButton" value="{translate key="common.save"}"/><input type="button" class="button" value="{translate key="common.cancel"}" onclick="history.go(-1)"/>
</form>

<p><span class="formRequired">{translate key="common.requiredField"}</span></p>
</div>
{include file="common/footer.tpl"}
Loading

0 comments on commit 864b307

Please sign in to comment.