-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Joshua Brule
committed
Feb 12, 2019
1 parent
b3b710a
commit 866fc99
Showing
9 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## Changelog | ||
|
||
3.0.0 Initial Version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
/** | ||
* Piwik - free/libre analytics platform | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
*/ | ||
|
||
namespace Piwik\Plugins\SiteAccessProvisioner; | ||
|
||
use Piwik\Piwik; | ||
use Piwik\Nonce; | ||
use Piwik\Notification; | ||
use Piwik\Common; | ||
use Piwik\Option; | ||
use Piwik\Settings\Storage; | ||
use Piwik\Settings\Setting; | ||
use Piwik\Plugin; | ||
use Piwik\Site; | ||
use Piwik\Url; | ||
use Piwik\View; | ||
|
||
class Controller extends \Piwik\Plugin\Controller | ||
{ | ||
const PLUGIN_NAME = "SiteAccessProvisioner"; | ||
|
||
public function index() | ||
{ | ||
|
||
} | ||
|
||
public function accessRequest() | ||
{ | ||
Piwik::checkUserIsNotAnonymous(); | ||
|
||
$idUser = trim(Common::getRequestVar('idUser', '', 'string',$_GET)); | ||
$site = Common::getRequestVar('site', 0, 'string',$_GET); | ||
$timestamp = Common::getRequestVar('timestamp', 0, 'int',$_GET); | ||
$token = Common::getRequestVar('token', 0, 'string',$_GET); | ||
|
||
list($msg, $idSite) = SiteAccessProvisioner::processRequest($idUser,$site,$timestamp,$token); | ||
|
||
if(!empty($msg)) | ||
{ | ||
$notification = new Notification($msg["message"]); | ||
$notification->context = ($msg["status"] === "success")? Notification::CONTEXT_SUCCESS : Notification::CONTEXT_ERROR; | ||
$notification->type = Notification::TYPE_TOAST; | ||
Notification\Manager::notify(self::PLUGIN_NAME."Notice", $notification); | ||
} | ||
|
||
$this->redirectToIndex('CoreHome', 'index', $idSite); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Matomo SiteAccessProvisioner Plugin | ||
|
||
##Description | ||
Plugin for the Matomo Web Analytics software package that facilitates an easy process to grant users access to site reports. A companion access provider is required, usually in the form of a website CMS plugin/module (you may need to build this if one does not exist). | ||
|
||
##Instructions | ||
The easiest way to install is to find the plugin in the [Matomo Marketplace](https://plugins.matomo.org/). | ||
A shared secret must be etablished before the plugin will function. | ||
You will then need to implement an access provider (see example code below) which will generate an access request link users can use. | ||
|
||
##Usage | ||
|
||
Implementation code for access provider. Should be trivial to port to other languages. | ||
```php | ||
$sharedSecret = "xxxxxxxxxxxxx"; //Shared secret. This needs to match the secret set in the Plugin settings. Should only be accessible by admin. | ||
$idUser = "myusername"; //Matomo username | ||
$site = "www.example.com/practicesubsite"; //URL of the site to request access for. Also accepts idSite. | ||
$timestamp = time(); | ||
$token = hash('sha256', implode('',[$sharedSecret, $idUser, $site, $timestamp])); | ||
|
||
$linkHref = sprintf("http://matomoinstall.example.com/matomo/index.php?%s", http_build_query(["module"=>"SiteAccessProvisioner", "action"=>"accessRequest", "idUser"=>$idUser, "site"=>$site, "timestamp"=>$timestamp, "token"=>$token])); | ||
``` | ||
##License | ||
GPL v3 / fair use | ||
|
||
## Support | ||
Please [report any issues](https://github.com/jbrule/matomoplugin-SiteAccessProvisioner/issues). Pull requests welcome. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<?php | ||
/** | ||
* Piwik - free/libre analytics platform | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
*/ | ||
|
||
namespace Piwik\Plugins\SiteAccessProvisioner; | ||
|
||
use Piwik\Piwik; | ||
use Piwik\Access; | ||
use Piwik\Common; | ||
use Piwik\Option; | ||
use Piwik\Settings\Storage; | ||
use Piwik\Settings\Setting; | ||
use Piwik\Plugins\SitesManager\API as APISitesManager; | ||
use Piwik\Plugins\UsersManager\API as APIUsersManager; | ||
|
||
class SiteAccessProvisioner extends \Piwik\Plugin | ||
{ | ||
public static function processRequest($idUser, $site, $timestamp, $token) | ||
{ | ||
$settings = new SystemSettings(); | ||
|
||
$sharedSecret = $settings->sharedSecret->getValue(); | ||
|
||
if(empty($sharedSecret)) | ||
{ | ||
throw new \Exception("Plugin function is inactive. Shared secret not set."); | ||
} | ||
|
||
$tokenttl = $settings->tokenttl->getValue(); | ||
|
||
$enforceMatchingUserId = $settings->enforceMatchingUserId->getValue(); | ||
|
||
$msg = array(); | ||
|
||
$idSite = false; | ||
|
||
$computedToken = hash('sha256',implode('',[$sharedSecret, $idUser, $site, $timestamp])); | ||
$currentTimestamp = time(); | ||
|
||
if($token === $computedToken && (!$enforceMatchingUserId || ($enforceMatchingUserId && strtolower($idUser) == strtolower(Piwik::getCurrentUserLogin())))) | ||
{ | ||
if(($currentTimestamp - $timestamp) <= $tokenttl) | ||
{ | ||
$idSite = (is_int($site))? $site : self::getIdSiteFromUrl($site); | ||
|
||
if($idSite !== false) | ||
{ | ||
if(!Piwik::isUserHasViewAccess($idSite) && !Piwik::isUserHasAdminAccess($idSite) && !Piwik::hasUserSuperUserAccess()) | ||
{ | ||
self::grantSiteAccess($idSite,"view"); | ||
if(Piwik::isUserHasViewAccess($idSite)) | ||
{ | ||
$msg["status"] = "success"; | ||
$msg["message"] = sprintf("You were successfully granted view access"); | ||
} | ||
} | ||
}else{ | ||
$msg["status"] = "error"; | ||
$msg["message"] = "Could not get idSite"; | ||
} | ||
|
||
}else{ | ||
$msg["status"] = "error"; | ||
$msg["message"] = "Access token has expired"; | ||
} | ||
}else{ | ||
$msg["status"] = "error"; | ||
$msg["message"] = "Invalid token"; | ||
} | ||
|
||
return [$msg, $idSite]; | ||
} | ||
|
||
private static function getIdSiteFromUrl($url) | ||
{ | ||
$result = Access::doAsSuperUser(function() use ($url){ | ||
$sitesManager = APISitesManager::getInstance(); | ||
return $sitesManager->getSitesIdFromSiteUrl($url); | ||
}); | ||
|
||
return (!empty($result))? $result[0]["idsite"] : false; | ||
} | ||
|
||
private static function grantSiteAccess($idSite, $accessLevel) | ||
{ | ||
$login = Piwik::getCurrentUserLogin(); | ||
|
||
return Access::doAsSuperUser(function() use ($login, $accessLevel, $idSite){ | ||
$usersManager = APIUsersManager::getInstance(); | ||
return $usersManager->setUserAccess($login, $accessLevel, $idSite); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php | ||
/** | ||
* Piwik - free/libre analytics platform | ||
* | ||
* @link http://piwik.org | ||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | ||
*/ | ||
|
||
namespace Piwik\Plugins\SiteAccessProvisioner; | ||
|
||
use Piwik\Settings\Setting; | ||
use Piwik\Settings\FieldConfig; | ||
use Piwik\Validators\NotEmpty; | ||
use Piwik\Validators\CharacterLength; | ||
use Piwik\Validators\NumberRange; | ||
|
||
class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings | ||
{ | ||
public $sharedSecret; | ||
|
||
public $tokenttl; | ||
|
||
public $enforceMatchingUserId; | ||
|
||
protected function init() | ||
{ | ||
$this->sharedSecret = $this->createSharedSecretSetting(); | ||
|
||
$this->tokenttl = $this->createTokenttlSetting(); | ||
|
||
$this->enforceMatchingUserId = $this->createEnforceMatchingUserIdSetting(); | ||
} | ||
|
||
private function createSharedSecretSetting() | ||
{ | ||
return $this->makeSetting('sharedSecret', $default = '', FieldConfig::TYPE_STRING, function (FieldConfig $field) { | ||
$field->title = 'Shared Secret'; | ||
$field->uiControl = FieldConfig::UI_CONTROL_TEXT; | ||
$field->description = 'Set the shared secret. This value should not be exposed to users.'; | ||
$field->inlineHelp = '<br /><strong>NOTICE:</strong> The access provider must use this same value for its secret.<br /><br /><a target="_blank" href="">How do I create an access provider?</a>'; | ||
$field->validators[] = new NotEmpty(); | ||
$field->validators[] = new CharacterLength(10,500); | ||
}); | ||
} | ||
|
||
private function createTokenttlSetting() | ||
{ | ||
return $this->makeSetting('Tokenttl', $default = 120, FieldConfig::TYPE_INT, function (FieldConfig $field) { | ||
$field->title = 'Token Time to Live'; | ||
$field->uiControl = FieldConfig::UI_CONTROL_TEXT; | ||
$field->description = 'Time (in seconds) that the token is valid for.'; | ||
$field->inlineHelp = '<br /><strong>NOTICE:</strong> If the access provider and Matomo server clocks are not in approximate sync, tokens may be flagged as expired.<br />'; | ||
$field->validators[] = new NotEmpty(); | ||
$field->validators[] = new NumberRange(1,3600); //1hr | ||
}); | ||
} | ||
|
||
private function createEnforceMatchingUserIdSetting() | ||
{ | ||
return $this->makeSetting('enforceMatchingUserId', $default = 1, FieldConfig::TYPE_BOOL, function (FieldConfig $field) { | ||
$field->title = 'UserId must match Matomo username'; | ||
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX; | ||
$field->description = 'Enforce checking if the idUser param provided by the access provider matches the logged in user.'; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
## FAQ | ||
|
||
__Why are accounts not being created?__ | ||
|
||
This plugin does not create user accounts. It just authorizes already existing accounts to view site tracking reports. If automatic account creation is desired I would suggest looking at the LdapLogin plugin in the Marketplace. | ||
You would need access to an Ldap directory for it to work however. | ||
|
||
__We are always seeing token expired error?__ | ||
|
||
If your access provider code and Matomo are on seprate servers this could be a symptom of the clocks on either server being incorrect. Using a service such as ntpd on Linux is highly recommended. If you have full control of your server lookup how to setup ntpd for your distribution. | ||
If you are using a hosting service and your system time is incorrect contact your hosting company to find out how to use the Network Time Protocol with your server. Timezone settings should not be a factor as we are using a UNIX TIMESTAMP for calculation. | ||
|
||
__I built an access provider for xxxx CMS. Would you like to be informed?__ | ||
|
||
Please let me know by [reporting as an issue](https://github.com/jbrule/matomoplugin-SiteAccessProvisioner/issues). Maintaining a directory can be a demanding job so I do not have plans to maintain an access provider directory at this time. | ||
If you create an access provider as a companion to this plugin please reference this plugin in your plugin/module documentation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Documentation | ||
|
||
The easiest way to install is to find the plugin in the [Matomo Marketplace](https://plugins.matomo.org/). | ||
After activation go to General Settings and set a SharedSecret. You will then need to implement an access provider (example code available in README) which will generate a link for users to use to access Matomo. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "SiteAccessProvisioner", | ||
"description": "Provides a simple method to provision access to site analytics. Integration with Content Management System is highly advised.", | ||
"version": "3.0.0", | ||
"theme": false, | ||
"require": { | ||
"piwik": ">=3.6.0-stable,<4.0.0-b1" | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Josh Brule", | ||
"email": "", | ||
"homepage": "https:\/\/www.linkedin.com\/pub\/joshua-brule\/15\/326\/9b9" | ||
} | ||
], | ||
"homepage": "https:\/\/github.com\/jbrule\/matomoplugin-SiteAccessProvisioner", | ||
"license": "GPL v3+", | ||
"keywords": ["access","authorization","integration"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{% extends 'dashboard.twig' %} | ||
|
||
{% block content %} | ||
<strong>Hello world!</strong> | ||
<br/> | ||
|
||
The answer to life is {{ answerToLife }} | ||
{% endblock %} |