diff options
author | Bjoern Schiessle <bjoern@schiessle.org> | 2016-08-08 12:48:42 +0300 |
---|---|---|
committer | Bjoern Schiessle <bjoern@schiessle.org> | 2016-08-08 19:05:20 +0300 |
commit | a6cef578781257e9e0a3c808a054d496862cbeed (patch) | |
tree | 770e0b3a711d03c822783f3b1e7cb26ddf99db52 /lib | |
parent | b5328ec249c0bc24a3b5ec4b57c185d16191b266 (diff) |
many small improvements to prepare the client for the Nextcloud 10 release
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AppInfo/Application.php | 62 | ||||
-rw-r--r-- | lib/BackgroundJobs/AdminNotification.php | 57 | ||||
-rw-r--r-- | lib/BackgroundJobs/MonthlyReport.php | 47 | ||||
-rw-r--r-- | lib/Categories/Apps.php | 91 | ||||
-rw-r--r-- | lib/Categories/Database.php | 208 | ||||
-rw-r--r-- | lib/Categories/Encryption.php | 78 | ||||
-rw-r--r-- | lib/Categories/FilesSharing.php | 128 | ||||
-rw-r--r-- | lib/Categories/ICategory.php | 46 | ||||
-rw-r--r-- | lib/Categories/Php.php | 90 | ||||
-rw-r--r-- | lib/Categories/Server.php | 87 | ||||
-rw-r--r-- | lib/Categories/Stats.php | 131 | ||||
-rw-r--r-- | lib/Collector.php | 189 | ||||
-rw-r--r-- | lib/Controller/EndpointController.php | 89 | ||||
-rw-r--r-- | lib/Notifier.php | 71 |
14 files changed, 1374 insertions, 0 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php new file mode 100644 index 0000000..a610dfc --- /dev/null +++ b/lib/AppInfo/Application.php @@ -0,0 +1,62 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\AppInfo; + +use OCA\Survey_Client\Controller\EndpointController; +use OCA\Survey_Client\Collector; +use OCP\AppFramework\App; +use OCP\IContainer; + +class Application extends App { + public function __construct (array $urlParams = array()) { + parent::__construct('survey_client', $urlParams); + $container = $this->getContainer(); + + $container->registerService('EndpointController', function(IContainer $c) { + /** @var \OC\Server $server */ + $server = $c->query('ServerContainer'); + + return new EndpointController( + $c->query('AppName'), + $server->getRequest(), + $c->query('OCA\Survey_Client\Collector'), + $server->getJobList(), + $server->getNotificationManager() + ); + }); + + $container->registerService('OCA\Survey_Client\Collector', function(IContainer $c) { + /** @var \OCP\IServerContainer $server */ + $server = $c->query('ServerContainer'); + + return new Collector( + $server->getHTTPClientService(), + $server->getConfig(), + $server->getDatabaseConnection(), + $server->getIniWrapper(), + $server->getL10NFactory()->get('survey_client') + ); + }); + + $container->registerCapability('Capabilities'); + } +} diff --git a/lib/BackgroundJobs/AdminNotification.php b/lib/BackgroundJobs/AdminNotification.php new file mode 100644 index 0000000..5aeeb51 --- /dev/null +++ b/lib/BackgroundJobs/AdminNotification.php @@ -0,0 +1,57 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\BackgroundJobs; + +use OC\BackgroundJob\QueuedJob; + +class AdminNotification extends QueuedJob { + protected function run($argument) { + $manager = \OC::$server->getNotificationManager(); + $urlGenerator = \OC::$server->getURLGenerator(); + + $notification = $manager->createNotification(); + $notification->setApp('survey_client') + ->setDateTime(new \DateTime()) + ->setSubject('updated') + ->setObject('dummy', 23) + ->setLink($urlGenerator->getAbsoluteURL('index.php/settings/admin#usage-report')); + + $enableAction = $notification->createAction(); + $enableAction->setLabel('enable') + ->setLink($urlGenerator->getAbsoluteURL('ocs/v2.php/apps/survey_client/api/v1/monthly'), 'POST') + ->setPrimary(true); + $notification->addAction($enableAction); + + $disableAction = $notification->createAction(); + $disableAction->setLabel('disable') + ->setLink($urlGenerator->getAbsoluteURL('ocs/v2.php/apps/survey_client/api/v1/monthly'), 'DELETE') + ->setPrimary(false); + $notification->addAction($disableAction); + + $adminGroup = \OC::$server->getGroupManager()->get('admin'); + foreach ($adminGroup->getUsers() as $admin) { + $notification->setUser($admin->getUID()); + $manager->notify($notification); + } + + } +} diff --git a/lib/BackgroundJobs/MonthlyReport.php b/lib/BackgroundJobs/MonthlyReport.php new file mode 100644 index 0000000..ccb0cc1 --- /dev/null +++ b/lib/BackgroundJobs/MonthlyReport.php @@ -0,0 +1,47 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\BackgroundJobs; + +use OC\BackgroundJob\TimedJob; +use OCA\Survey_Client\AppInfo\Application; + +class MonthlyReport extends TimedJob { + + /** + * MonthlyReport constructor. + */ + public function __construct() { + // Run all 28 days + $this->setInterval(28 * 24 * 60 * 60); + } + + protected function run($argument) { + $application = new Application(); + /** @var \OCA\Survey_Client\Collector $collector */ + $collector = $application->getContainer()->query('OCA\Survey_Client\Collector'); + $result = $collector->sendReport(); + + if (!$result->succeeded()) { + \OC::$server->getLogger()->info('Error while sending usage statistic'); + } + } +} diff --git a/lib/Categories/Apps.php b/lib/Categories/Apps.php new file mode 100644 index 0000000..b5b3333 --- /dev/null +++ b/lib/Categories/Apps.php @@ -0,0 +1,91 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use Doctrine\DBAL\Connection; +use OCP\IDBConnection; +use OCP\IL10N; + +/** + * Class Apps + * + * @package OCA\Survey_Client\Categories + */ +class Apps implements ICategory { + /** @var IDBConnection */ + protected $connection; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IDBConnection $connection + * @param IL10N $l + */ + public function __construct(IDBConnection $connection, IL10N $l) { + $this->connection = $connection; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'apps'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('App list <em>(for each app: name, version, is enabled?)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + $query = $this->connection->getQueryBuilder(); + + $query->select('*') + ->from('appconfig') + ->where($query->expr()->in('configkey', $query->createNamedParameter( + ['enabled', 'installed_version'], + Connection::PARAM_STR_ARRAY + ))); + $result = $query->execute(); + + $data = []; + while ($row = $result->fetch()) { + if ($row['configkey'] === 'enabled' && $row['configvalue'] === 'no') { + $data[$row['appid']] = 'disabled'; + } + if ($row['configkey'] === 'installed_version' && !isset($data[$row['appid']])) { + $data[$row['appid']] = $row['configvalue']; + } + } + $result->closeCursor(); + + return $data; + } +} diff --git a/lib/Categories/Database.php b/lib/Categories/Database.php new file mode 100644 index 0000000..fe2d4c1 --- /dev/null +++ b/lib/Categories/Database.php @@ -0,0 +1,208 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; + +/** + * Class Database + * + * @package OCA\Survey_Client\Categories + */ +class Database implements ICategory { + /** @var \OCP\IConfig */ + protected $config; + + /** @var \OCP\IDBConnection */ + protected $connection; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IConfig $config + * @param IDBConnection $connection + * @param IL10N $l + */ + public function __construct(IConfig $config, IDBConnection $connection, IL10N $l) { + $this->config = $config; + $this->connection = $connection; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'database'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('Database environment <em>(type, version, database size)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + return [ + 'type' => $this->config->getSystemValue('dbtype'), + 'version' => $this->databaseVersion(), + 'size' => $this->databaseSize(), + ]; + } + + protected function databaseVersion() { + switch ($this->config->getSystemValue('dbtype')) { + case 'sqlite': + case 'sqlite3': + $sql = 'SELECT sqlite_version() AS version'; + break; + + case 'oci': + $sql = 'SELECT version FROM v$instance'; + break; + + case 'mysql': + case 'pgsql': + default: + $sql = 'SELECT VERSION() AS version'; + break; + } + + $result = $this->connection->executeQuery($sql); + $row = $result->fetch(); + $result->closeCursor(); + + if ($row) { + return $this->cleanVersion($row['version']); + } + + return 'N/A'; + } + + /** + * Copy of phpBB's get_database_size() + * @link https://github.com/phpbb/phpbb/blob/release-3.1.6/phpBB/includes/functions_admin.php#L2908-L3043 + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * @return int|string + */ + protected function databaseSize() { + $database_size = false; + + // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 + switch ($this->config->getSystemValue('dbtype')) { + case 'mysql': + $sql = 'SELECT VERSION() AS mysql_version'; + $result = $this->connection->executeQuery($sql); + $row = $result->fetch(); + $result->closeCursor(); + + if ($row) { + $version = $row['mysql_version']; + if (preg_match('#(3\.23|[45]\.)#', $version)) { + $db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$this->config->getSystemValue('dbname')}`" : $this->config->getSystemValue('dbname'); + $sql = 'SHOW TABLE STATUS + FROM ' . $db_name; + $result = $this->connection->executeQuery($sql); + $database_size = 0; + while ($row = $result->fetch()) { + if ((isset($row['Type']) && $row['Type'] != 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] == 'MyISAM' || $row['Engine'] == 'InnoDB'))) { + $database_size += $row['Data_length'] + $row['Index_length']; + } + } + $result->closeCursor(); + } + } + break; + + case 'sqlite': + if (file_exists($this->config->getSystemValue('dbhost'))) { + $database_size = filesize($this->config->getSystemValue('dbhost')); + } + break; + + case 'pgsql': + $sql = "SELECT proname + FROM pg_proc + WHERE proname = 'pg_database_size'"; + $result = $this->connection->executeQuery($sql); + $row = $result->fetch(); + $result->closeCursor(); + if ($row['proname'] == 'pg_database_size') { + $database = $this->config->getSystemValue('dbname'); + if (strpos($database, '.') !== false) + { + list($database, ) = explode('.', $database); + } + $sql = "SELECT oid + FROM pg_database + WHERE datname = '$database'"; + $result = $this->connection->executeQuery($sql); + $row = $result->fetch(); + $result->closeCursor(); + $oid = $row['oid']; + $sql = 'SELECT pg_database_size(' . $oid . ') as size'; + $result = $this->connection->executeQuery($sql); + $row = $result->fetch(); + $result->closeCursor(); + $database_size = $row['size']; + } + break; + + case 'oci': + $sql = 'SELECT SUM(bytes) as dbsize + FROM user_segments'; + $result = $this->connection->executeQuery($sql); + $database_size = ($row = $result->fetch()) ? $row['dbsize'] : false; + $result->closeCursor(); + break; + } + + return ($database_size !== false) ? $database_size : 'N/A'; + } + + /** + * Try to strip away additional information + * + * @param string $version E.g. `5.6.27-0ubuntu0.14.04.1` + * @return string `5.6.27` + */ + protected function cleanVersion($version) { + $matches = []; + preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches); + if (isset($matches[0])) { + return $matches[0]; + } + + return $version; + } +} diff --git a/lib/Categories/Encryption.php b/lib/Categories/Encryption.php new file mode 100644 index 0000000..72334d4 --- /dev/null +++ b/lib/Categories/Encryption.php @@ -0,0 +1,78 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use OCP\IConfig; +use OCP\IL10N; + +/** + * Class Encryption + * + * @package OCA\Survey_Client\Categories + */ +class Encryption implements ICategory { + /** @var \OCP\IConfig */ + protected $config; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IConfig $config + * @param IL10N $l + */ + public function __construct(IConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'encryption'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('Encryption information <em>(is it enabled?, what is the default module)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + $data = [ + 'enabled' => $this->config->getAppValue('core', 'encryption_enabled', 'no') ? 'yes' : 'no', + 'default_module' => $this->config->getAppValue('core', 'default_encryption_module') === 'OC_DEFAULT_MODULE' ? 'yes' : 'no', + ]; + + if ($data['enabled'] === 'yes') { + unset($data['default_module']); + } + + return $data; + } +} diff --git a/lib/Categories/FilesSharing.php b/lib/Categories/FilesSharing.php new file mode 100644 index 0000000..16164d8 --- /dev/null +++ b/lib/Categories/FilesSharing.php @@ -0,0 +1,128 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use OCP\IDBConnection; +use OCP\IL10N; + +/** + * Class FilesSharing + * + * @package OCA\Survey_Client\Categories + */ +class FilesSharing implements ICategory { + /** @var IDBConnection */ + protected $connection; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IDBConnection $connection + * @param IL10N $l + */ + public function __construct(IDBConnection $connection, IL10N $l) { + $this->connection = $connection; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'files_sharing'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('Number of shares <em>(per type and permission setting)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->addSelect(['permissions', 'share_type']) + ->from('share') + ->groupBy('permissions') + ->groupBy('share_type'); + $result = $query->execute(); + + $data = [ + 'num_shares' => $this->countEntries('share'), + 'num_shares_user' => $this->countShares(0), + 'num_shares_groups' => $this->countShares(1), + 'num_shares_link' => $this->countShares(3), + 'num_shares_link_no_password' => $this->countShares(3, true), + 'num_fed_shares_sent' => $this->countShares(6), + 'num_fed_shares_received' => $this->countEntries('share_external'), + ]; + while ($row = $result->fetch()) { + $data['permissions_' . $row['share_type'] . '_' . $row['permissions']] = $row['num_entries']; + } + $result->closeCursor(); + + return $data; + } + + /** + * @param string $tableName + * @return int + */ + protected function countEntries($tableName) { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->from($tableName); + $result = $query->execute(); + $row = $result->fetch(); + $result->closeCursor(); + + return (int) $row['num_entries']; + } + + /** + * @param int $type + * @param bool $noShareWith + * @return int + */ + protected function countShares($type, $noShareWith = false) { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->from('share') + ->where($query->expr()->eq('share_type', $query->createNamedParameter($type))); + + if ($noShareWith) { + $query->andWhere($query->expr()->isNull('share_with')); + } + + $result = $query->execute(); + $row = $result->fetch(); + $result->closeCursor(); + + return (int) $row['num_entries']; + } +} diff --git a/lib/Categories/ICategory.php b/lib/Categories/ICategory.php new file mode 100644 index 0000000..c5a7f5d --- /dev/null +++ b/lib/Categories/ICategory.php @@ -0,0 +1,46 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + +/** + * Interface ICategory + * + * TODO Move to core public API? + * + * @package OCA\Survey_Client\Categories + */ +interface ICategory { + /** + * @return string + */ + public function getCategory(); + + /** + * @return string + */ + public function getDisplayName(); + + /** + * @return array (string => string|int) + */ + public function getData(); +} diff --git a/lib/Categories/Php.php b/lib/Categories/Php.php new file mode 100644 index 0000000..cd30ab4 --- /dev/null +++ b/lib/Categories/Php.php @@ -0,0 +1,90 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use bantu\IniGetWrapper\IniGetWrapper; +use OCP\IL10N; + +/** + * Class php + * + * @package OCA\Survey_Client\Categories + */ +class Php implements ICategory { + /** @var IniGetWrapper */ + protected $phpIni; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IniGetWrapper $phpIni + * @param IL10N $l + */ + public function __construct(IniGetWrapper $phpIni, IL10N $l) { + $this->phpIni = $phpIni; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'php'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('PHP environment <em>(version, memory limit, max. execution time, max. file size)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + return [ + 'version' => $this->cleanVersion(PHP_VERSION), + 'memory_limit' => $this->phpIni->getBytes('memory_limit'), + 'max_execution_time' => $this->phpIni->getNumeric('max_execution_time'), + 'upload_max_filesize' => $this->phpIni->getBytes('upload_max_filesize'), + ]; + } + + /** + * Try to strip away additional information + * + * @param string $version E.g. `5.5.30-1+deb.sury.org~trusty+1` + * @return string `5.5.30` + */ + protected function cleanVersion($version) { + $matches = []; + preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches); + if (isset($matches[0])) { + return $matches[0]; + } + + return $version; + } +} diff --git a/lib/Categories/Server.php b/lib/Categories/Server.php new file mode 100644 index 0000000..c3307a1 --- /dev/null +++ b/lib/Categories/Server.php @@ -0,0 +1,87 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use OCP\IConfig; +use OCP\IL10N; + +/** + * Class Server + * + * @package OCA\Survey_Client\Categories + */ +class Server implements ICategory { + /** @var \OCP\IConfig */ + protected $config; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IConfig $config + * @param IL10N $l + */ + public function __construct(IConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'server'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('Server instance details <em>(version, memcache used, locking/previews/avatars enabled?)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + return [ + 'version' => $this->config->getSystemValue('version'), + 'code' => $this->codeLocation(), + 'enable_avatars' => $this->config->getSystemValue('enable_avatars', true) ? 'yes' : 'no', + 'enable_previews' => $this->config->getSystemValue('enable_previews', true) ? 'yes' : 'no', + 'memcache.local' => $this->config->getSystemValue('memcache.local', 'none'), + 'memcache.distributed' => $this->config->getSystemValue('memcache.distributed', 'none'), + 'asset-pipeline.enabled' => $this->config->getSystemValue('asset-pipeline.enabled') ? 'yes' : 'no', + 'filelocking.enabled' => $this->config->getSystemValue('filelocking.enabled', true) ? 'yes' : 'no', + 'memcache.locking' => $this->config->getSystemValue('memcache.locking', 'none'), + 'debug' => $this->config->getSystemValue('debug', false) ? 'yes' : 'no', + ]; + } + + protected function codeLocation() { + if (file_exists(\OC::$SERVERROOT . '/.git') && is_dir(\OC::$SERVERROOT . '/.git')) { + return 'git'; + } + return 'other'; + } +} diff --git a/lib/Categories/Stats.php b/lib/Categories/Stats.php new file mode 100644 index 0000000..08df7a7 --- /dev/null +++ b/lib/Categories/Stats.php @@ -0,0 +1,131 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Categories; + + +use OCP\IDBConnection; +use OCP\IL10N; + +/** + * Class Stats + * + * @package OCA\Survey_Client\Categories + */ +class Stats implements ICategory { + /** @var IDBConnection */ + protected $connection; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * @param IDBConnection $connection + * @param IL10N $l + */ + public function __construct(IDBConnection $connection, IL10N $l) { + $this->connection = $connection; + $this->l = $l; + } + + /** + * @return string + */ + public function getCategory() { + return 'stats'; + } + + /** + * @return string + */ + public function getDisplayName() { + return (string) $this->l->t('Statistic <em>(number of: files, users, storages per type)</em>'); + } + + /** + * @return array (string => string|int) + */ + public function getData() { + return [ + 'num_files' => $this->countEntries('filecache'), + 'num_users' => $this->countUserEntries(), + 'num_storages' => $this->countEntries('storages'), + 'num_storages_local' => $this->countStorages('local'), + 'num_storages_home' => $this->countStorages('home'), + 'num_storages_other' => $this->countStorages('other'), + ]; + } + + /** + * @return int + */ + protected function countUserEntries() { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->from('preferences') + ->where($query->expr()->eq('configkey', $query->createNamedParameter('lastLogin'))); + $result = $query->execute(); + $row = $result->fetch(); + $result->closeCursor(); + + return (int) $row['num_entries']; + } + + /** + * @param string $type + * @return int + */ + protected function countStorages($type) { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->from('storages'); + + if ($type === 'home') { + $query->where($query->expr()->like('id', $query->createNamedParameter('home::%'))); + } else if ($type === 'local') { + $query->where($query->expr()->like('id', $query->createNamedParameter('local::%'))); + } else if ($type === 'other') { + $query->where($query->expr()->notLike('id', $query->createNamedParameter('home::%'))); + $query->andWhere($query->expr()->notLike('id', $query->createNamedParameter('local::%'))); + } + + $result = $query->execute(); + $row = $result->fetch(); + $result->closeCursor(); + + return (int) $row['num_entries']; + } + + /** + * @param string $tableName + * @return int + */ + protected function countEntries($tableName) { + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') + ->from($tableName); + $result = $query->execute(); + $row = $result->fetch(); + $result->closeCursor(); + + return (int) $row['num_entries']; + } +} diff --git a/lib/Collector.php b/lib/Collector.php new file mode 100644 index 0000000..89e4a4d --- /dev/null +++ b/lib/Collector.php @@ -0,0 +1,189 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client; + +use bantu\IniGetWrapper\IniGetWrapper; +use OCA\Survey_Client\Categories\Apps; +use OCA\Survey_Client\Categories\Database; +use OCA\Survey_Client\Categories\Encryption; +use OCA\Survey_Client\Categories\FilesSharing; +use OCA\Survey_Client\Categories\ICategory; +use OCA\Survey_Client\Categories\Php; +use OCA\Survey_Client\Categories\Server; +use OCA\Survey_Client\Categories\Stats; +use OCP\AppFramework\Http; +use OCP\Http\Client\IClientService; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; + +class Collector { + + const SURVEY_SERVER_URL = 'https://surveyserver.nextcloud.com/'; + + /** @var ICategory[] */ + protected $categories; + + /** @var IClientService */ + protected $clientService; + + /** @var IConfig */ + protected $config; + + /** @var IDBConnection */ + protected $connection; + + /** @var IniGetWrapper */ + protected $phpIni; + + /** @var \OCP\IL10N */ + protected $l; + + /** + * Collector constructor. + * + * @param IClientService $clientService + * @param IConfig $config + * @param IDBConnection $connection + * @param IniGetWrapper $phpIni + * @param IL10N $l + */ + public function __construct(IClientService $clientService, IConfig $config, IDBConnection $connection, IniGetWrapper $phpIni, IL10N $l) { + $this->clientService = $clientService; + $this->config = $config; + $this->connection = $connection; + $this->phpIni = $phpIni; + $this->l = $l; + } + + protected function registerCategories() { + $this->categories[] = new Server( + $this->config, + $this->l + ); + $this->categories[] = new php( + $this->phpIni, + $this->l + ); + $this->categories[] = new Database( + $this->config, + $this->connection, + $this->l + ); + $this->categories[] = new Apps( + $this->connection, + $this->l + ); + $this->categories[] = new Stats( + $this->connection, + $this->l + ); + $this->categories[] = new FilesSharing( + $this->connection, + $this->l + ); + $this->categories[] = new Encryption( + $this->config, + $this->l + ); + } + + /** + * @return array + */ + public function getCategories() { + $this->registerCategories(); + + $categories = []; + + foreach ($this->categories as $category) { + $categories[$category->getCategory()] = [ + 'displayName' => $category->getDisplayName(), + 'enabled' => $this->config->getAppValue('survey_client', $category->getCategory(), 'yes') === 'yes', + ]; + } + + return $categories; + } + + /** + * @return array + */ + public function getReport() { + $this->registerCategories(); + + $tuples = []; + foreach ($this->categories as $category) { + if ($this->config->getAppValue('survey_client', $category->getCategory(), 'yes') === 'yes') { + foreach ($category->getData() as $key => $value) { + $tuples[] = [ + $category->getCategory(), + $key, + $value + ]; + } + } + } + + return [ + 'id' => $this->config->getSystemValue('instanceid'), + 'items' => $tuples, + ]; + } + + /** + * @return \OC_OCS_Result + */ + public function sendReport() { + $report = $this->getReport(); + + $client = $this->clientService->newClient(); + + try { + $response = $client->post(self::SURVEY_SERVER_URL . 'ocs/v2.php/apps/survey_server/api/v1/survey', [ + 'timeout' => 5, + 'query' => [ + 'data' => json_encode($report), + ], + ]); + } catch (\Exception $e) { + return new \OC_OCS_Result( + $report, + Http::STATUS_INTERNAL_SERVER_ERROR + ); + } + + if ($response->getStatusCode() === Http::STATUS_OK) { + $this->config->setAppValue('survey_client', 'last_sent', time()); + $this->config->setAppValue('survey_client', 'last_report', json_encode($report)); + return new \OC_OCS_Result( + $report, + 100// HTTP::STATUS_OK, TODO: <status>failure</status><statuscode>200</statuscode> + ); + } + + return new \OC_OCS_Result( + $report, + Http::STATUS_INTERNAL_SERVER_ERROR + ); + } +} diff --git a/lib/Controller/EndpointController.php b/lib/Controller/EndpointController.php new file mode 100644 index 0000000..6b21ddf --- /dev/null +++ b/lib/Controller/EndpointController.php @@ -0,0 +1,89 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client\Controller; + +use OCA\Survey_Client\Collector; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; +use OCP\IRequest; +use OCP\Notification\IManager; + +class EndpointController extends Controller { + + /** @var Collector */ + protected $collector; + + /** @var IJobList */ + protected $jobList; + + /** @var IManager */ + protected $manager; + + /** + * @param string $appName + * @param IRequest $request + * @param Collector $collector + * @param IJobList $jobList + * @param IManager $manager + */ + public function __construct($appName, IRequest $request, Collector $collector, IJobList $jobList, IManager $manager) { + parent::__construct($appName, $request); + + $this->collector = $collector; + $this->jobList = $jobList; + $this->manager = $manager; + } + + /** + * @return \OC_OCS_Result + */ + public function enableMonthly() { + $this->jobList->add('OCA\Survey_Client\BackgroundJobs\MonthlyReport'); + + $notification = $this->manager->createNotification(); + $notification->setApp('survey_client'); + $this->manager->markProcessed($notification); + + return new \OC_OCS_Result(); + } + + /** + * @return \OC_OCS_Result + */ + public function disableMonthly() { + $this->jobList->remove('OCA\Survey_Client\BackgroundJobs\MonthlyReport'); + + $notification = $this->manager->createNotification(); + $notification->setApp('survey_client'); + $this->manager->markProcessed($notification); + + return new \OC_OCS_Result(); + } + + /** + * @return \OC_OCS_Result + */ + public function sendReport() { + return $this->collector->sendReport(); + } +} diff --git a/lib/Notifier.php b/lib/Notifier.php new file mode 100644 index 0000000..995551f --- /dev/null +++ b/lib/Notifier.php @@ -0,0 +1,71 @@ +<?php +/** + * @author Joas Schilling <coding@schilljs.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\Survey_Client; + +use OCP\L10N\IFactory; +use OCP\Notification\INotification; +use OCP\Notification\INotifier; + +class Notifier implements INotifier { + + /** @var IFactory */ + protected $l10nFactory; + + /** + * Notifier constructor. + * + * @param IFactory $l10nFactory + */ + public function __construct(IFactory $l10nFactory) { + $this->l10nFactory = $l10nFactory; + } + + /** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + * @return INotification + * @throws \InvalidArgumentException When the notification was not prepared by a notifier + */ + public function prepare(INotification $notification, $languageCode) { + if ($notification->getApp() !== 'survey_client') { + // Not my app => throw + throw new \InvalidArgumentException(); + } + + // Read the language from the notification + $l = $this->l10nFactory->get('survey_client', $languageCode); + + $notification->setParsedSubject((string) $l->t( + 'Do you want to help us to improve Nextcloud by providing some anonymized data about your setup and usage? You can disable it at any time in the admin settings again.')); + + foreach ($notification->getActions() as $action) { + if ($action->getLabel() === 'disable') { + $action->setParsedLabel((string) $l->t('Not now')); + } else if ($action->getLabel() === 'enable') { + $action->setParsedLabel((string) $l->t('Send usage')); + } + $notification->addParsedAction($action); + } + + return $notification; + } +} |