Add SSO for updater application

Allows logging-in into the updater application by visiting the admin panel and pressing "Open updater".
This commit is contained in:
Lukas Reschke 2016-02-09 19:58:29 +01:00
parent a39c7591d6
commit b9e3ed1468
12 changed files with 491 additions and 1 deletions

1
.gitignore vendored
View File

@ -22,6 +22,7 @@
!/apps/user_ldap !/apps/user_ldap
!/apps/provisioning_api !/apps/provisioning_api
!/apps/systemtags !/apps/systemtags
!/apps/updatenotification
/apps/files_external/3rdparty/irodsphp/PHPUnitTest /apps/files_external/3rdparty/irodsphp/PHPUnitTest
/apps/files_external/3rdparty/irodsphp/web /apps/files_external/3rdparty/irodsphp/web
/apps/files_external/3rdparty/irodsphp/prods/test /apps/files_external/3rdparty/irodsphp/prods/test

View File

@ -0,0 +1,25 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
$app = new \OCA\UpdateNotification\AppInfo\Application();
/** @var OCA\UpdateNotification\Controller\AdminController $controller */
$controller = $app->getContainer()->query('AdminController');
return $controller->displayPanel()->render();

View File

@ -36,4 +36,6 @@ if(\OC::$server->getConfig()->getSystemValue('updatechecker', true) === true) {
OC_Hook::connect('\OCP\Config', 'js', $updateChecker, 'getJavaScript'); OC_Hook::connect('\OCP\Config', 'js', $updateChecker, 'getJavaScript');
} }
} }
\OC_App::registerAdmin('updatenotification', 'admin');
} }

View File

@ -0,0 +1,46 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification\AppInfo;
use OC\AppFramework\Utility\TimeFactory;
use OCA\UpdateNotification\Controller\AdminController;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
class Application extends App {
public function __construct (array $urlParams = array()) {
parent::__construct('updatenotification', $urlParams);
$container = $this->getContainer();
$container->registerService('AdminController', function(IAppContainer $c) {
return new AdminController(
$c->query('AppName'),
$c->query('Request'),
$c->getServer()->getJobList(),
$c->getServer()->getSecureRandom(),
$c->getServer()->getConfig(),
new TimeFactory()
);
});
}
}

View File

@ -2,7 +2,7 @@
<info> <info>
<id>updatenotification</id> <id>updatenotification</id>
<name>Update notification</name> <name>Update notification</name>
<description>Displays update notifications for ownCloud.</description> <description>Displays update notifications for ownCloud and provides the SSO for the updater.</description>
<licence>AGPL</licence> <licence>AGPL</licence>
<author>Lukas Reschke</author> <author>Lukas Reschke</author>
<version>0.1.0</version> <version>0.1.0</version>

View File

@ -0,0 +1,27 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification\AppInfo;
$application = new Application();
$application->registerRoutes($this, ['routes' => [
['name' => 'Admin#createCredentials', 'url' => '/credentials', 'verb' => 'GET'],
]]);

View File

@ -0,0 +1,85 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IRequest;
use OCP\Security\ISecureRandom;
class AdminController extends Controller {
/** @var IJobList */
private $jobList;
/** @var ISecureRandom */
private $secureRandom;
/** @var IConfig */
private $config;
/** @var ITimeFactory */
private $timeFactory;
/**
* @param string $appName
* @param IRequest $request
* @param IJobList $jobList
* @param ISecureRandom $secureRandom
* @param IConfig $config
* @param ITimeFactory $timeFactory
*/
public function __construct($appName,
IRequest $request,
IJobList $jobList,
ISecureRandom $secureRandom,
IConfig $config,
ITimeFactory $timeFactory) {
parent::__construct($appName, $request);
$this->jobList = $jobList;
$this->secureRandom = $secureRandom;
$this->config = $config;
$this->timeFactory = $timeFactory;
}
/**
* @return TemplateResponse
*/
public function displayPanel() {
return new TemplateResponse($this->appName, 'admin', [], '');
}
/**
* @return DataResponse
*/
public function createCredentials() {
// Create a new job and store the creation date
$this->jobList->add('OCA\UpdateNotification\ResetTokenBackgroundJob');
$this->config->setAppValue('core', 'updater.secret.created', $this->timeFactory->getTime());
// Create a new token
$newToken = $this->secureRandom->generate(32);
$this->config->setSystemValue('updater.secret', $newToken);
return new DataResponse($newToken);
}
}

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2016 ownCloud Inc
*
* @author Lukas Reschke <lukas@owncloud.com>
*
* This file is licensed under the Affero General Public License version 3
* or later.
*
* See the COPYING-README file.
*
*/
/**
* Creates a new authentication token and loads the updater URL
*/
var loginToken = '';
$(document).ready(function(){
$('#oca_updatenotification').click(function() {
// Load the new token
$.ajax({
url: OC.generateUrl('/apps/updatenotification/credentials')
}).success(function(data) {
loginToken = data;
$.ajax({
url: OC.webroot+'/updater/',
headers: {
'Authorization': loginToken
},
method: 'POST',
success: function(data){
if(data !== 'false') {
var body = $('body');
$('head').remove();
body.html(data);
body.removeAttr('id');
body.attr('id', 'body-settings');
}
}
});
});
});
});

View File

@ -0,0 +1,75 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification;
use OC\AppFramework\Utility\TimeFactory;
use OC\BackgroundJob\TimedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
/**
* Class ResetTokenBackgroundJob deletes any configured token all 24 hours for
*
*
* @package OCA\UpdateNotification
*/
class ResetTokenBackgroundJob extends TimedJob {
/** @var IConfig */
private $config;
/** @var ITimeFactory */
private $timeFactory;
/**
* @param IConfig|null $config
* @param ITimeFactory|null $timeFactory
*/
public function __construct(IConfig $config = null,
ITimeFactory $timeFactory = null) {
// Run all 10 minutes
$this->setInterval(60 * 10);
if ($config instanceof IConfig && $timeFactory instanceof ITimeFactory) {
$this->config = $config;
$this->timeFactory = $timeFactory;
} else {
$this->fixDIForJobs();
}
}
/**
* DI for jobs
*/
private function fixDIForJobs() {
$this->config = \OC::$server->getConfig();
$this->timeFactory = new TimeFactory();
}
/**
* @param $argument
*/
protected function run($argument) {
if($this->timeFactory->getTime() - $this->config->getAppValue('core', 'updater.secret.created', $this->timeFactory->getTime()) >= 86400) {
$this->config->deleteSystemValue('updater.secret');
}
}
}

View File

@ -0,0 +1,8 @@
<?php script('updatenotification', 'admin') ?>
<form id="oca_updatenotification" class="section">
<h2><?php p($l->t('Updater')); ?></h2>
<p>
<?php p($l->t('For security reasons the built-in ownCloud updater is using additional credentials. To visit the updater page please click the following button.')) ?>
</p>
<input type="button" id="oca_updatenotification" value="<?php p($l->t('Open updater')) ?>">
</form>

View File

@ -0,0 +1,81 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification\Tests;
use OCA\UpdateNotification\ResetTokenBackgroundJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use Test\TestCase;
class ResetTokenBackgroundJobTest extends TestCase {
/** @var IConfig */
private $config;
/** @var ResetTokenBackgroundJob */
private $resetTokenBackgroundJob;
/** @var ITimeFactory */
private $timeFactory;
public function setUp() {
parent::setUp();
$this->config = $this->getMock('\\OCP\\IConfig');
$this->timeFactory = $this->getMock('\\OCP\\AppFramework\\Utility\\ITimeFactory');
$this->resetTokenBackgroundJob = new ResetTokenBackgroundJob($this->config, $this->timeFactory);
}
public function testRunWithNotExpiredToken() {
$this->timeFactory
->expects($this->any())
->method('getTime')
->willReturn(123);
$this->config
->expects($this->once())
->method('getAppValue')
->with('core', 'updater.secret.created', 123);
$this->config
->expects($this->never())
->method('deleteSystemValue')
->with('updater.secret');
$this->invokePrivate($this->resetTokenBackgroundJob, 'run', ['']);
}
public function testRunWithExpiredToken() {
$this->timeFactory
->expects($this->at(0))
->method('getTime')
->willReturn(1455131633);
$this->timeFactory
->expects($this->at(1))
->method('getTime')
->willReturn(1455045234);
$this->config
->expects($this->once())
->method('getAppValue')
->with('core', 'updater.secret.created', 1455045234);
$this->config
->expects($this->once())
->method('deleteSystemValue')
->with('updater.secret');
$this->invokePrivate($this->resetTokenBackgroundJob, 'run', ['']);
}
}

View File

@ -0,0 +1,98 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\UpdateNotification\Tests\Controller;
use OCA\UpdateNotification\Controller\AdminController;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IRequest;
use OCP\Security\ISecureRandom;
use Test\TestCase;
class AdminControllerTest extends TestCase {
/** @var IRequest */
private $request;
/** @var IJobList */
private $jobList;
/** @var ISecureRandom */
private $secureRandom;
/** @var IConfig */
private $config;
/** @var AdminController */
private $adminController;
/** @var ITimeFactory */
private $timeFactory;
public function setUp() {
parent::setUp();
$this->request = $this->getMock('\\OCP\\IRequest');
$this->jobList = $this->getMock('\\OCP\\BackgroundJob\\IJobList');
$this->secureRandom = $this->getMock('\\OCP\\Security\\ISecureRandom');
$this->config = $this->getMock('\\OCP\\IConfig');
$this->timeFactory = $this->getMock('\\OCP\\AppFramework\\Utility\\ITimeFactory');
$this->adminController = new AdminController(
'updatenotification',
$this->request,
$this->jobList,
$this->secureRandom,
$this->config,
$this->timeFactory
);
}
public function testDisplayPanel() {
$expected = new TemplateResponse('updatenotification', 'admin', [], '');
$this->assertEquals($expected, $this->adminController->displayPanel());
}
public function testCreateCredentials() {
$this->jobList
->expects($this->once())
->method('add')
->with('OCA\UpdateNotification\ResetTokenBackgroundJob');
$this->secureRandom
->expects($this->once())
->method('generate')
->with(32)
->willReturn('MyGeneratedToken');
$this->config
->expects($this->once())
->method('setSystemValue')
->with('updater.secret', 'MyGeneratedToken');
$this->timeFactory
->expects($this->once())
->method('getTime')
->willReturn(12345);
$this->config
->expects($this->once())
->method('setAppValue')
->with('core', 'updater.secret.created', 12345);
$expected = new DataResponse('MyGeneratedToken');
$this->assertEquals($expected, $this->adminController->createCredentials());
}
}