From 9ad4a898163fc71ec8366378123aec90fd872fbb Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 3 May 2016 10:00:17 +0200 Subject: Move comments, systemtags and updatenotifications to PSR-4 --- apps/comments/activity/extension.php | 329 -------------------- apps/comments/activity/listener.php | 128 -------- apps/comments/lib/Activity/Extension.php | 329 ++++++++++++++++++++ apps/comments/lib/Activity/Listener.php | 128 ++++++++ apps/systemtags/activity/extension.php | 335 --------------------- apps/systemtags/activity/listener.php | 223 -------------- apps/systemtags/appinfo/info.xml | 1 + apps/systemtags/lib/Activity/Extension.php | 335 +++++++++++++++++++++ apps/systemtags/lib/Activity/Listener.php | 223 ++++++++++++++ apps/updatenotification/appinfo/application.php | 55 ---- apps/updatenotification/appinfo/info.xml | 1 + apps/updatenotification/appinfo/routes.php | 2 +- .../controller/admincontroller.php | 140 --------- .../updatenotification/lib/AppInfo/Application.php | 55 ++++ .../lib/Controller/AdminController.php | 140 +++++++++ .../lib/ResetTokenBackgroundJob.php | 76 +++++ apps/updatenotification/lib/UpdateChecker.php | 67 +++++ .../lib/resettokenbackgroundjob.php | 76 ----- apps/updatenotification/lib/updatechecker.php | 67 ----- .../tests/Controller/AdminControllerTest.php | 192 ++++++++++++ .../tests/controller/AdminControllerTest.php | 192 ------------ 21 files changed, 1548 insertions(+), 1546 deletions(-) delete mode 100644 apps/comments/activity/extension.php delete mode 100644 apps/comments/activity/listener.php create mode 100644 apps/comments/lib/Activity/Extension.php create mode 100644 apps/comments/lib/Activity/Listener.php delete mode 100644 apps/systemtags/activity/extension.php delete mode 100644 apps/systemtags/activity/listener.php create mode 100644 apps/systemtags/lib/Activity/Extension.php create mode 100644 apps/systemtags/lib/Activity/Listener.php delete mode 100644 apps/updatenotification/appinfo/application.php delete mode 100644 apps/updatenotification/controller/admincontroller.php create mode 100644 apps/updatenotification/lib/AppInfo/Application.php create mode 100644 apps/updatenotification/lib/Controller/AdminController.php create mode 100644 apps/updatenotification/lib/ResetTokenBackgroundJob.php create mode 100644 apps/updatenotification/lib/UpdateChecker.php delete mode 100644 apps/updatenotification/lib/resettokenbackgroundjob.php delete mode 100644 apps/updatenotification/lib/updatechecker.php create mode 100644 apps/updatenotification/tests/Controller/AdminControllerTest.php delete mode 100644 apps/updatenotification/tests/controller/AdminControllerTest.php (limited to 'apps') diff --git a/apps/comments/activity/extension.php b/apps/comments/activity/extension.php deleted file mode 100644 index ef800e88abc..00000000000 --- a/apps/comments/activity/extension.php +++ /dev/null @@ -1,329 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\Comments\Activity; - -use OCP\Activity\IExtension; -use OCP\Activity\IManager; -use OCP\Comments\ICommentsManager; -use OCP\Comments\NotFoundException; -use OCP\IL10N; -use OCP\IURLGenerator; -use OCP\L10N\IFactory; - -/** - * Class Extension - * - * @package OCA\Comments\Activity - */ -class Extension implements IExtension { - const APP_NAME = 'comments'; - - const ADD_COMMENT_SUBJECT = 'add_comment_subject'; - const ADD_COMMENT_MESSAGE = 'add_comment_message'; - - /** @var IFactory */ - protected $languageFactory; - - /** @var IManager */ - protected $activityManager; - - /** @var ICommentsManager */ - protected $commentsManager; - - /** @var IURLGenerator */ - protected $URLGenerator; - - /** - * @param IFactory $languageFactory - * @param IManager $activityManager - * @param ICommentsManager $commentsManager - * @param IURLGenerator $URLGenerator - */ - public function __construct(IFactory $languageFactory, IManager $activityManager, ICommentsManager $commentsManager, IURLGenerator $URLGenerator) { - $this->languageFactory = $languageFactory; - $this->activityManager = $activityManager; - $this->commentsManager = $commentsManager; - $this->URLGenerator = $URLGenerator; - } - - protected function getL10N($languageCode = null) { - return $this->languageFactory->get(self::APP_NAME, $languageCode); - } - - /** - * The extension can return an array of additional notification types. - * If no additional types are to be added false is to be returned - * - * @param string $languageCode - * @return array|false - */ - public function getNotificationTypes($languageCode) { - $l = $this->getL10N($languageCode); - - return array( - self::APP_NAME => [ - 'desc' => (string) $l->t('Comments for files (always listed in stream)'), - 'methods' => [self::METHOD_MAIL], // self::METHOD_STREAM is forced true by the default value - ], - ); - } - - /** - * For a given method additional types to be displayed in the settings can be returned. - * In case no additional types are to be added false is to be returned. - * - * @param string $method - * @return array|false - */ - public function getDefaultTypes($method) { - return $method === self::METHOD_STREAM ? [self::APP_NAME] : false; - } - - /** - * A string naming the css class for the icon to be used can be returned. - * If no icon is known for the given type false is to be returned. - * - * @param string $type - * @return string|false - */ - public function getTypeIcon($type) { - switch ($type) { - case self::APP_NAME: - return 'icon-comment'; - } - - return false; - } - - /** - * The extension can translate a given message to the requested languages. - * If no translation is available false is to be returned. - * - * @param string $app - * @param string $text - * @param array $params - * @param boolean $stripPath - * @param boolean $highlightParams - * @param string $languageCode - * @return string|false - */ - public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { - if ($app !== self::APP_NAME) { - return false; - } - - $l = $this->getL10N($languageCode); - - if ($this->activityManager->isFormattingFilteredObject()) { - $translation = $this->translateShort($text, $l, $params); - if ($translation !== false) { - return $translation; - } - } - - return $this->translateLong($text, $l, $params); - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateShort($text, IL10N $l, array $params) { - - switch ($text) { - case self::ADD_COMMENT_SUBJECT: - if ($this->authorIsCurrentUser($params[0])) { - return (string) $l->t('You commented'); - } - return (string) $l->t('%1$s commented', $params); - case self::ADD_COMMENT_MESSAGE: - return $this->convertParameterToComment($params[0], 120); - } - - return false; - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateLong($text, IL10N $l, array $params) { - - switch ($text) { - case self::ADD_COMMENT_SUBJECT: - if ($this->authorIsCurrentUser($params[0])) { - return (string) $l->t('You commented on %2$s', $params); - } - return (string) $l->t('%1$s commented on %2$s', $params); - case self::ADD_COMMENT_MESSAGE: - return $this->convertParameterToComment($params[0]); - } - - return false; - } - - /** - * Check if the author is the current user - * - * @param string $user Parameter e.g. `admin` - * @return bool - */ - protected function authorIsCurrentUser($user) { - try { - return strip_tags($user) === $this->activityManager->getCurrentUserId(); - } catch (\UnexpectedValueException $e) { - // FIXME this is awkward, but we have no access to the current user in emails - return false; - } - } - - /** - * The extension can define the type of parameters for translation - * - * Currently known types are: - * * file => will strip away the path of the file and add a tooltip with it - * * username => will add the avatar of the user - * - * @param string $app - * @param string $text - * @return array|false - */ - public function getSpecialParameterList($app, $text) { - if ($app === self::APP_NAME) { - switch ($text) { - case self::ADD_COMMENT_SUBJECT: - return [ - 0 => 'username', - 1 => 'file', - ]; - } - } - - return false; - } - - /** - * The extension can define the parameter grouping by returning the index as integer. - * In case no grouping is required false is to be returned. - * - * @param array $activity - * @return integer|false - */ - public function getGroupParameter($activity) { - return false; - } - - /** - * The extension can define additional navigation entries. The array returned has to contain two keys 'top' - * and 'apps' which hold arrays with the relevant entries. - * If no further entries are to be added false is no be returned. - * - * @return array|false - */ - public function getNavigation() { - $l = $this->getL10N(); - return [ - 'apps' => [], - 'top' => [ - self::APP_NAME => [ - 'id' => self::APP_NAME, - 'name' => (string) $l->t('Comments'), - 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::APP_NAME]), - ], - ], - ]; - } - - /** - * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. - * - * @param string $filterValue - * @return boolean - */ - public function isFilterValid($filterValue) { - return $filterValue === self::APP_NAME; - } - - /** - * The extension can filter the types based on the filter if required. - * In case no filter is to be applied false is to be returned unchanged. - * - * @param array $types - * @param string $filter - * @return array|false - */ - public function filterNotificationTypes($types, $filter) { - if ($filter === self::APP_NAME) { - return [self::APP_NAME]; - } - if (in_array($filter, ['all', 'by', 'self', 'filter'])) { - $types[] = self::APP_NAME; - return $types; - } - return false; - } - - /** - * For a given filter the extension can specify the sql query conditions including parameters for that query. - * In case the extension does not know the filter false is to be returned. - * The query condition and the parameters are to be returned as array with two elements. - * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); - * - * @param string $filter - * @return array|false - */ - public function getQueryForFilter($filter) { - return false; - } - - /** - * @param string $parameter - * @return string - */ - protected function convertParameterToComment($parameter, $maxLength = 0) { - if (preg_match('/^\(\d*)\<\/parameter\>$/', $parameter, $matches)) { - try { - $comment = $this->commentsManager->get((int) $matches[1]); - $message = $comment->getMessage(); - $message = str_replace("\n", '
', str_replace(['<', '>'], ['<', '>'], $message)); - - if ($maxLength && isset($message[$maxLength + 20])) { - $findSpace = strpos($message, ' ', $maxLength); - if ($findSpace !== false && $findSpace < $maxLength + 20) { - return substr($message, 0, $findSpace) . '…'; - } - return substr($message, 0, $maxLength + 20) . '…'; - } - - return $message; - } catch (NotFoundException $e) { - return ''; - } - } - - return ''; - } -} diff --git a/apps/comments/activity/listener.php b/apps/comments/activity/listener.php deleted file mode 100644 index 7c6970df837..00000000000 --- a/apps/comments/activity/listener.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\Comments\Activity; - -use OCP\Activity\IManager; -use OCP\App\IAppManager; -use OCP\Comments\CommentsEvent; -use OCP\Files\Config\IMountProviderCollection; -use OCP\Files\IRootFolder; -use OCP\Files\Node; -use OCP\IUser; -use OCP\IUserSession; -use OCP\Share; - -class Listener { - /** @var IManager */ - protected $activityManager; - /** @var IUserSession */ - protected $session; - /** @var \OCP\App\IAppManager */ - protected $appManager; - /** @var \OCP\Files\Config\IMountProviderCollection */ - protected $mountCollection; - /** @var \OCP\Files\IRootFolder */ - protected $rootFolder; - - /** - * Listener constructor. - * - * @param IManager $activityManager - * @param IUserSession $session - * @param IAppManager $appManager - * @param IMountProviderCollection $mountCollection - * @param IRootFolder $rootFolder - */ - public function __construct(IManager $activityManager, - IUserSession $session, - IAppManager $appManager, - IMountProviderCollection $mountCollection, - IRootFolder $rootFolder) { - $this->activityManager = $activityManager; - $this->session = $session; - $this->appManager = $appManager; - $this->mountCollection = $mountCollection; - $this->rootFolder = $rootFolder; - } - - /** - * @param CommentsEvent $event - */ - public function commentEvent(CommentsEvent $event) { - if ($event->getComment()->getObjectType() !== 'files' - || !in_array($event->getEvent(), [CommentsEvent::EVENT_ADD]) - || !$this->appManager->isInstalled('activity')) { - // Comment not for file, not adding a comment or no activity-app enabled (save the energy) - return; - } - - // Get all mount point owners - $cache = $this->mountCollection->getMountCache(); - $mounts = $cache->getMountsForFileId($event->getComment()->getObjectId()); - if (empty($mounts)) { - return; - } - - $users = []; - foreach ($mounts as $mount) { - $owner = $mount->getUser()->getUID(); - $ownerFolder = $this->rootFolder->getUserFolder($owner); - $nodes = $ownerFolder->getById($event->getComment()->getObjectId()); - if (!empty($nodes)) { - /** @var Node $node */ - $node = array_shift($nodes); - $path = $node->getPath(); - if (strpos($path, '/' . $owner . '/files/') === 0) { - $path = substr($path, strlen('/' . $owner . '/files')); - } - // Get all users that have access to the mount point - $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); - } - } - - $actor = $this->session->getUser(); - if ($actor instanceof IUser) { - $actor = $actor->getUID(); - } else { - $actor = ''; - } - - $activity = $this->activityManager->generateEvent(); - $activity->setApp(Extension::APP_NAME) - ->setType(Extension::APP_NAME) - ->setAuthor($actor) - ->setObject($event->getComment()->getObjectType(), $event->getComment()->getObjectId()) - ->setMessage(Extension::ADD_COMMENT_MESSAGE, [ - $event->getComment()->getId(), - ]); - - foreach ($users as $user => $path) { - $activity->setAffectedUser($user); - - $activity->setSubject(Extension::ADD_COMMENT_SUBJECT, [ - $actor, - $path, - ]); - $this->activityManager->publish($activity); - } - } -} diff --git a/apps/comments/lib/Activity/Extension.php b/apps/comments/lib/Activity/Extension.php new file mode 100644 index 00000000000..ef800e88abc --- /dev/null +++ b/apps/comments/lib/Activity/Extension.php @@ -0,0 +1,329 @@ + + * + * @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 + * + */ + +namespace OCA\Comments\Activity; + +use OCP\Activity\IExtension; +use OCP\Activity\IManager; +use OCP\Comments\ICommentsManager; +use OCP\Comments\NotFoundException; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\L10N\IFactory; + +/** + * Class Extension + * + * @package OCA\Comments\Activity + */ +class Extension implements IExtension { + const APP_NAME = 'comments'; + + const ADD_COMMENT_SUBJECT = 'add_comment_subject'; + const ADD_COMMENT_MESSAGE = 'add_comment_message'; + + /** @var IFactory */ + protected $languageFactory; + + /** @var IManager */ + protected $activityManager; + + /** @var ICommentsManager */ + protected $commentsManager; + + /** @var IURLGenerator */ + protected $URLGenerator; + + /** + * @param IFactory $languageFactory + * @param IManager $activityManager + * @param ICommentsManager $commentsManager + * @param IURLGenerator $URLGenerator + */ + public function __construct(IFactory $languageFactory, IManager $activityManager, ICommentsManager $commentsManager, IURLGenerator $URLGenerator) { + $this->languageFactory = $languageFactory; + $this->activityManager = $activityManager; + $this->commentsManager = $commentsManager; + $this->URLGenerator = $URLGenerator; + } + + protected function getL10N($languageCode = null) { + return $this->languageFactory->get(self::APP_NAME, $languageCode); + } + + /** + * The extension can return an array of additional notification types. + * If no additional types are to be added false is to be returned + * + * @param string $languageCode + * @return array|false + */ + public function getNotificationTypes($languageCode) { + $l = $this->getL10N($languageCode); + + return array( + self::APP_NAME => [ + 'desc' => (string) $l->t('Comments for files (always listed in stream)'), + 'methods' => [self::METHOD_MAIL], // self::METHOD_STREAM is forced true by the default value + ], + ); + } + + /** + * For a given method additional types to be displayed in the settings can be returned. + * In case no additional types are to be added false is to be returned. + * + * @param string $method + * @return array|false + */ + public function getDefaultTypes($method) { + return $method === self::METHOD_STREAM ? [self::APP_NAME] : false; + } + + /** + * A string naming the css class for the icon to be used can be returned. + * If no icon is known for the given type false is to be returned. + * + * @param string $type + * @return string|false + */ + public function getTypeIcon($type) { + switch ($type) { + case self::APP_NAME: + return 'icon-comment'; + } + + return false; + } + + /** + * The extension can translate a given message to the requested languages. + * If no translation is available false is to be returned. + * + * @param string $app + * @param string $text + * @param array $params + * @param boolean $stripPath + * @param boolean $highlightParams + * @param string $languageCode + * @return string|false + */ + public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { + if ($app !== self::APP_NAME) { + return false; + } + + $l = $this->getL10N($languageCode); + + if ($this->activityManager->isFormattingFilteredObject()) { + $translation = $this->translateShort($text, $l, $params); + if ($translation !== false) { + return $translation; + } + } + + return $this->translateLong($text, $l, $params); + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateShort($text, IL10N $l, array $params) { + + switch ($text) { + case self::ADD_COMMENT_SUBJECT: + if ($this->authorIsCurrentUser($params[0])) { + return (string) $l->t('You commented'); + } + return (string) $l->t('%1$s commented', $params); + case self::ADD_COMMENT_MESSAGE: + return $this->convertParameterToComment($params[0], 120); + } + + return false; + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateLong($text, IL10N $l, array $params) { + + switch ($text) { + case self::ADD_COMMENT_SUBJECT: + if ($this->authorIsCurrentUser($params[0])) { + return (string) $l->t('You commented on %2$s', $params); + } + return (string) $l->t('%1$s commented on %2$s', $params); + case self::ADD_COMMENT_MESSAGE: + return $this->convertParameterToComment($params[0]); + } + + return false; + } + + /** + * Check if the author is the current user + * + * @param string $user Parameter e.g. `admin` + * @return bool + */ + protected function authorIsCurrentUser($user) { + try { + return strip_tags($user) === $this->activityManager->getCurrentUserId(); + } catch (\UnexpectedValueException $e) { + // FIXME this is awkward, but we have no access to the current user in emails + return false; + } + } + + /** + * The extension can define the type of parameters for translation + * + * Currently known types are: + * * file => will strip away the path of the file and add a tooltip with it + * * username => will add the avatar of the user + * + * @param string $app + * @param string $text + * @return array|false + */ + public function getSpecialParameterList($app, $text) { + if ($app === self::APP_NAME) { + switch ($text) { + case self::ADD_COMMENT_SUBJECT: + return [ + 0 => 'username', + 1 => 'file', + ]; + } + } + + return false; + } + + /** + * The extension can define the parameter grouping by returning the index as integer. + * In case no grouping is required false is to be returned. + * + * @param array $activity + * @return integer|false + */ + public function getGroupParameter($activity) { + return false; + } + + /** + * The extension can define additional navigation entries. The array returned has to contain two keys 'top' + * and 'apps' which hold arrays with the relevant entries. + * If no further entries are to be added false is no be returned. + * + * @return array|false + */ + public function getNavigation() { + $l = $this->getL10N(); + return [ + 'apps' => [], + 'top' => [ + self::APP_NAME => [ + 'id' => self::APP_NAME, + 'name' => (string) $l->t('Comments'), + 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::APP_NAME]), + ], + ], + ]; + } + + /** + * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. + * + * @param string $filterValue + * @return boolean + */ + public function isFilterValid($filterValue) { + return $filterValue === self::APP_NAME; + } + + /** + * The extension can filter the types based on the filter if required. + * In case no filter is to be applied false is to be returned unchanged. + * + * @param array $types + * @param string $filter + * @return array|false + */ + public function filterNotificationTypes($types, $filter) { + if ($filter === self::APP_NAME) { + return [self::APP_NAME]; + } + if (in_array($filter, ['all', 'by', 'self', 'filter'])) { + $types[] = self::APP_NAME; + return $types; + } + return false; + } + + /** + * For a given filter the extension can specify the sql query conditions including parameters for that query. + * In case the extension does not know the filter false is to be returned. + * The query condition and the parameters are to be returned as array with two elements. + * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); + * + * @param string $filter + * @return array|false + */ + public function getQueryForFilter($filter) { + return false; + } + + /** + * @param string $parameter + * @return string + */ + protected function convertParameterToComment($parameter, $maxLength = 0) { + if (preg_match('/^\(\d*)\<\/parameter\>$/', $parameter, $matches)) { + try { + $comment = $this->commentsManager->get((int) $matches[1]); + $message = $comment->getMessage(); + $message = str_replace("\n", '
', str_replace(['<', '>'], ['<', '>'], $message)); + + if ($maxLength && isset($message[$maxLength + 20])) { + $findSpace = strpos($message, ' ', $maxLength); + if ($findSpace !== false && $findSpace < $maxLength + 20) { + return substr($message, 0, $findSpace) . '…'; + } + return substr($message, 0, $maxLength + 20) . '…'; + } + + return $message; + } catch (NotFoundException $e) { + return ''; + } + } + + return ''; + } +} diff --git a/apps/comments/lib/Activity/Listener.php b/apps/comments/lib/Activity/Listener.php new file mode 100644 index 00000000000..7c6970df837 --- /dev/null +++ b/apps/comments/lib/Activity/Listener.php @@ -0,0 +1,128 @@ + + * + * @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 + * + */ + +namespace OCA\Comments\Activity; + +use OCP\Activity\IManager; +use OCP\App\IAppManager; +use OCP\Comments\CommentsEvent; +use OCP\Files\Config\IMountProviderCollection; +use OCP\Files\IRootFolder; +use OCP\Files\Node; +use OCP\IUser; +use OCP\IUserSession; +use OCP\Share; + +class Listener { + /** @var IManager */ + protected $activityManager; + /** @var IUserSession */ + protected $session; + /** @var \OCP\App\IAppManager */ + protected $appManager; + /** @var \OCP\Files\Config\IMountProviderCollection */ + protected $mountCollection; + /** @var \OCP\Files\IRootFolder */ + protected $rootFolder; + + /** + * Listener constructor. + * + * @param IManager $activityManager + * @param IUserSession $session + * @param IAppManager $appManager + * @param IMountProviderCollection $mountCollection + * @param IRootFolder $rootFolder + */ + public function __construct(IManager $activityManager, + IUserSession $session, + IAppManager $appManager, + IMountProviderCollection $mountCollection, + IRootFolder $rootFolder) { + $this->activityManager = $activityManager; + $this->session = $session; + $this->appManager = $appManager; + $this->mountCollection = $mountCollection; + $this->rootFolder = $rootFolder; + } + + /** + * @param CommentsEvent $event + */ + public function commentEvent(CommentsEvent $event) { + if ($event->getComment()->getObjectType() !== 'files' + || !in_array($event->getEvent(), [CommentsEvent::EVENT_ADD]) + || !$this->appManager->isInstalled('activity')) { + // Comment not for file, not adding a comment or no activity-app enabled (save the energy) + return; + } + + // Get all mount point owners + $cache = $this->mountCollection->getMountCache(); + $mounts = $cache->getMountsForFileId($event->getComment()->getObjectId()); + if (empty($mounts)) { + return; + } + + $users = []; + foreach ($mounts as $mount) { + $owner = $mount->getUser()->getUID(); + $ownerFolder = $this->rootFolder->getUserFolder($owner); + $nodes = $ownerFolder->getById($event->getComment()->getObjectId()); + if (!empty($nodes)) { + /** @var Node $node */ + $node = array_shift($nodes); + $path = $node->getPath(); + if (strpos($path, '/' . $owner . '/files/') === 0) { + $path = substr($path, strlen('/' . $owner . '/files')); + } + // Get all users that have access to the mount point + $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); + } + } + + $actor = $this->session->getUser(); + if ($actor instanceof IUser) { + $actor = $actor->getUID(); + } else { + $actor = ''; + } + + $activity = $this->activityManager->generateEvent(); + $activity->setApp(Extension::APP_NAME) + ->setType(Extension::APP_NAME) + ->setAuthor($actor) + ->setObject($event->getComment()->getObjectType(), $event->getComment()->getObjectId()) + ->setMessage(Extension::ADD_COMMENT_MESSAGE, [ + $event->getComment()->getId(), + ]); + + foreach ($users as $user => $path) { + $activity->setAffectedUser($user); + + $activity->setSubject(Extension::ADD_COMMENT_SUBJECT, [ + $actor, + $path, + ]); + $this->activityManager->publish($activity); + } + } +} diff --git a/apps/systemtags/activity/extension.php b/apps/systemtags/activity/extension.php deleted file mode 100644 index 8c101a6f550..00000000000 --- a/apps/systemtags/activity/extension.php +++ /dev/null @@ -1,335 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\SystemTags\Activity; - -use OCP\Activity\IExtension; -use OCP\Activity\IManager; -use OCP\IL10N; -use OCP\L10N\IFactory; - -/** - * Class Extension - * - * @package OCA\SystemTags\Activity - */ -class Extension implements IExtension { - const APP_NAME = 'systemtags'; - - const CREATE_TAG = 'create_tag'; - const UPDATE_TAG = 'update_tag'; - const DELETE_TAG = 'delete_tag'; - - const ASSIGN_TAG = 'assign_tag'; - const UNASSIGN_TAG = 'unassign_tag'; - - /** @var IFactory */ - protected $languageFactory; - - /** @var IManager */ - protected $activityManager; - - /** - * @param IFactory $languageFactory - * @param IManager $activityManager - */ - public function __construct(IFactory $languageFactory, IManager $activityManager) { - $this->languageFactory = $languageFactory; - $this->activityManager = $activityManager; - } - - protected function getL10N($languageCode = null) { - return $this->languageFactory->get(self::APP_NAME, $languageCode); - } - - /** - * The extension can return an array of additional notification types. - * If no additional types are to be added false is to be returned - * - * @param string $languageCode - * @return array|false - */ - public function getNotificationTypes($languageCode) { - $l = $this->getL10N($languageCode); - - return array( - self::APP_NAME => (string) $l->t('System tags for a file have been modified'), - ); - } - - /** - * For a given method additional types to be displayed in the settings can be returned. - * In case no additional types are to be added false is to be returned. - * - * @param string $method - * @return array|false - */ - public function getDefaultTypes($method) { - return $method === self::METHOD_STREAM ? [self::APP_NAME] : false; - } - - /** - * A string naming the css class for the icon to be used can be returned. - * If no icon is known for the given type false is to be returned. - * - * @param string $type - * @return string|false - */ - public function getTypeIcon($type) { - switch ($type) { - case self::APP_NAME: - return false; - } - - return false; - } - - /** - * The extension can translate a given message to the requested languages. - * If no translation is available false is to be returned. - * - * @param string $app - * @param string $text - * @param array $params - * @param boolean $stripPath - * @param boolean $highlightParams - * @param string $languageCode - * @return string|false - */ - public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { - if ($app !== self::APP_NAME) { - return false; - } - - $l = $this->getL10N($languageCode); - - if ($this->activityManager->isFormattingFilteredObject()) { - $translation = $this->translateShort($text, $l, $params); - if ($translation !== false) { - return $translation; - } - } - - return $this->translateLong($text, $l, $params); - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateShort($text, IL10N $l, array $params) { - - switch ($text) { - case self::ASSIGN_TAG: - $params[2] = $this->convertParameterToTag($params[2], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You assigned system tag %3$s', $params); - } - return (string) $l->t('%1$s assigned system tag %3$s', $params); - case self::UNASSIGN_TAG: - $params[2] = $this->convertParameterToTag($params[2], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You unassigned system tag %3$s', $params); - } - return (string) $l->t('%1$s unassigned system tag %3$s', $params); - } - - return false; - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateLong($text, IL10N $l, array $params) { - - switch ($text) { - case self::CREATE_TAG: - $params[1] = $this->convertParameterToTag($params[1], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You created system tag %2$s', $params); - } - return (string) $l->t('%1$s created system tag %2$s', $params); - case self::DELETE_TAG: - $params[1] = $this->convertParameterToTag($params[1], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You deleted system tag %2$s', $params); - } - return (string) $l->t('%1$s deleted system tag %2$s', $params); - case self::UPDATE_TAG: - $params[1] = $this->convertParameterToTag($params[1], $l); - $params[2] = $this->convertParameterToTag($params[2], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You updated system tag %3$s to %2$s', $params); - } - return (string) $l->t('%1$s updated system tag %3$s to %2$s', $params); - case self::ASSIGN_TAG: - $params[2] = $this->convertParameterToTag($params[2], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You assigned system tag %3$s to %2$s', $params); - } - return (string) $l->t('%1$s assigned system tag %3$s to %2$s', $params); - case self::UNASSIGN_TAG: - $params[2] = $this->convertParameterToTag($params[2], $l); - if ($this->actorIsCurrentUser($params[0])) { - return (string) $l->t('You unassigned system tag %3$s from %2$s', $params); - } - return (string) $l->t('%1$s unassigned system tag %3$s from %2$s', $params); - } - - return false; - } - - /** - * Check if the author is the current user - * - * @param string $user Parameter e.g. `admin` - * @return bool - */ - protected function actorIsCurrentUser($user) { - try { - return strip_tags($user) === $this->activityManager->getCurrentUserId(); - } catch (\UnexpectedValueException $e) { - return false; - } - } - - /** - * The extension can define the type of parameters for translation - * - * Currently known types are: - * * file => will strip away the path of the file and add a tooltip with it - * * username => will add the avatar of the user - * - * @param string $app - * @param string $text - * @return array|false - */ - public function getSpecialParameterList($app, $text) { - if ($app === self::APP_NAME) { - switch ($text) { - case self::CREATE_TAG: - case self::DELETE_TAG: - return array( - 0 => 'username', - //1 => 'systemtag description', - ); - case self::UPDATE_TAG: - return array( - 0 => 'username', - //1 => 'systemtag description', - //2 => 'systemtag description', - ); - - case self::ASSIGN_TAG: - case self::UNASSIGN_TAG: - return array( - 0 => 'username', - 1 => 'file', - //2 => 'systemtag description', - ); - } - } - - return false; - } - - /** - * The extension can define the parameter grouping by returning the index as integer. - * In case no grouping is required false is to be returned. - * - * @param array $activity - * @return integer|false - */ - public function getGroupParameter($activity) { - return false; - } - - /** - * The extension can define additional navigation entries. The array returned has to contain two keys 'top' - * and 'apps' which hold arrays with the relevant entries. - * If no further entries are to be added false is no be returned. - * - * @return array|false - */ - public function getNavigation() { - return false; - } - - /** - * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. - * - * @param string $filterValue - * @return boolean - */ - public function isFilterValid($filterValue) { - return false; - } - - /** - * The extension can filter the types based on the filter if required. - * In case no filter is to be applied false is to be returned unchanged. - * - * @param array $types - * @param string $filter - * @return array|false - */ - public function filterNotificationTypes($types, $filter) { - return false; - } - - /** - * For a given filter the extension can specify the sql query conditions including parameters for that query. - * In case the extension does not know the filter false is to be returned. - * The query condition and the parameters are to be returned as array with two elements. - * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); - * - * @param string $filter - * @return array|false - */ - public function getQueryForFilter($filter) { - return false; - } - - /** - * @param string $parameter - * @param IL10N $l - * @return string - */ - protected function convertParameterToTag($parameter, IL10N $l) { - if (preg_match('/^\\{\{\{(.*)\|\|\|(.*)\}\}\}\<\/parameter\>$/', $parameter, $matches)) { - switch ($matches[2]) { - case 'assignable': - return '' . $matches[1] . ''; - case 'not-assignable': - return '' . $l->t('%s (not-assignable)', $matches[1]) . ''; - case 'invisible': - return '' . $l->t('%s (invisible)', $matches[1]) . ''; - } - } - - return $parameter; - } -} diff --git a/apps/systemtags/activity/listener.php b/apps/systemtags/activity/listener.php deleted file mode 100644 index 9b6597119c6..00000000000 --- a/apps/systemtags/activity/listener.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\SystemTags\Activity; - -use OCP\Activity\IManager; -use OCP\App\IAppManager; -use OCP\Files\Config\IMountProviderCollection; -use OCP\Files\IRootFolder; -use OCP\Files\Node; -use OCP\IGroup; -use OCP\IGroupManager; -use OCP\IUser; -use OCP\IUserSession; -use OCP\Share; -use OCP\SystemTag\ISystemTag; -use OCP\SystemTag\ISystemTagManager; -use OCP\SystemTag\ManagerEvent; -use OCP\SystemTag\MapperEvent; -use OCP\SystemTag\TagNotFoundException; - -class Listener { - /** @var IGroupManager */ - protected $groupManager; - /** @var IManager */ - protected $activityManager; - /** @var IUserSession */ - protected $session; - /** @var \OCP\SystemTag\ISystemTagManager */ - protected $tagManager; - /** @var \OCP\App\IAppManager */ - protected $appManager; - /** @var \OCP\Files\Config\IMountProviderCollection */ - protected $mountCollection; - /** @var \OCP\Files\IRootFolder */ - protected $rootFolder; - - /** - * Listener constructor. - * - * @param IGroupManager $groupManager - * @param IManager $activityManager - * @param IUserSession $session - * @param ISystemTagManager $tagManager - * @param IAppManager $appManager - * @param IMountProviderCollection $mountCollection - * @param IRootFolder $rootFolder - */ - public function __construct(IGroupManager $groupManager, - IManager $activityManager, - IUserSession $session, - ISystemTagManager $tagManager, - IAppManager $appManager, - IMountProviderCollection $mountCollection, - IRootFolder $rootFolder) { - $this->groupManager = $groupManager; - $this->activityManager = $activityManager; - $this->session = $session; - $this->tagManager = $tagManager; - $this->appManager = $appManager; - $this->mountCollection = $mountCollection; - $this->rootFolder = $rootFolder; - } - - /** - * @param ManagerEvent $event - */ - public function event(ManagerEvent $event) { - $actor = $this->session->getUser(); - if ($actor instanceof IUser) { - $actor = $actor->getUID(); - } else { - $actor = ''; - } - - $activity = $this->activityManager->generateEvent(); - $activity->setApp(Extension::APP_NAME) - ->setType(Extension::APP_NAME) - ->setAuthor($actor); - if ($event->getEvent() === ManagerEvent::EVENT_CREATE) { - $activity->setSubject(Extension::CREATE_TAG, [ - $actor, - $this->prepareTagAsParameter($event->getTag()), - ]); - } else if ($event->getEvent() === ManagerEvent::EVENT_UPDATE) { - $activity->setSubject(Extension::UPDATE_TAG, [ - $actor, - $this->prepareTagAsParameter($event->getTag()), - $this->prepareTagAsParameter($event->getTagBefore()), - ]); - } else if ($event->getEvent() === ManagerEvent::EVENT_DELETE) { - $activity->setSubject(Extension::DELETE_TAG, [ - $actor, - $this->prepareTagAsParameter($event->getTag()), - ]); - } else { - return; - } - - $group = $this->groupManager->get('admin'); - if ($group instanceof IGroup) { - foreach ($group->getUsers() as $user) { - $activity->setAffectedUser($user->getUID()); - $this->activityManager->publish($activity); - } - } - } - - /** - * @param MapperEvent $event - */ - public function mapperEvent(MapperEvent $event) { - $tagIds = $event->getTags(); - if ($event->getObjectType() !== 'files' ||empty($tagIds) - || !in_array($event->getEvent(), [MapperEvent::EVENT_ASSIGN, MapperEvent::EVENT_UNASSIGN]) - || !$this->appManager->isInstalled('activity')) { - // System tags not for files, no tags, not (un-)assigning or no activity-app enabled (save the energy) - return; - } - - try { - $tags = $this->tagManager->getTagsByIds($tagIds); - } catch (TagNotFoundException $e) { - // User assigned/unassigned a non-existing tag, ignore... - return; - } - - if (empty($tags)) { - return; - } - - // Get all mount point owners - $cache = $this->mountCollection->getMountCache(); - $mounts = $cache->getMountsForFileId($event->getObjectId()); - if (empty($mounts)) { - return; - } - - $users = []; - foreach ($mounts as $mount) { - $owner = $mount->getUser()->getUID(); - $ownerFolder = $this->rootFolder->getUserFolder($owner); - $nodes = $ownerFolder->getById($event->getObjectId()); - if (!empty($nodes)) { - /** @var Node $node */ - $node = array_shift($nodes); - $path = $node->getPath(); - if (strpos($path, '/' . $owner . '/files/') === 0) { - $path = substr($path, strlen('/' . $owner . '/files')); - } - // Get all users that have access to the mount point - $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); - } - } - - $actor = $this->session->getUser(); - if ($actor instanceof IUser) { - $actor = $actor->getUID(); - } else { - $actor = ''; - } - - $activity = $this->activityManager->generateEvent(); - $activity->setApp(Extension::APP_NAME) - ->setType(Extension::APP_NAME) - ->setAuthor($actor) - ->setObject($event->getObjectType(), $event->getObjectId()); - - foreach ($users as $user => $path) { - $activity->setAffectedUser($user); - - foreach ($tags as $tag) { - if ($event->getEvent() === MapperEvent::EVENT_ASSIGN) { - $activity->setSubject(Extension::ASSIGN_TAG, [ - $actor, - $path, - $this->prepareTagAsParameter($tag), - ]); - } else if ($event->getEvent() === MapperEvent::EVENT_UNASSIGN) { - $activity->setSubject(Extension::UNASSIGN_TAG, [ - $actor, - $path, - $this->prepareTagAsParameter($tag), - ]); - } - - $this->activityManager->publish($activity); - } - } - } - - /** - * @param ISystemTag $tag - * @return string - */ - protected function prepareTagAsParameter(ISystemTag $tag) { - if (!$tag->isUserVisible()) { - return '{{{' . $tag->getName() . '|||invisible}}}'; - } else if (!$tag->isUserAssignable()) { - return '{{{' . $tag->getName() . '|||not-assignable}}}'; - } else { - return '{{{' . $tag->getName() . '|||assignable}}}'; - } - } -} diff --git a/apps/systemtags/appinfo/info.xml b/apps/systemtags/appinfo/info.xml index 5df740f699e..b593b1134b1 100644 --- a/apps/systemtags/appinfo/info.xml +++ b/apps/systemtags/appinfo/info.xml @@ -11,6 +11,7 @@ + SystemTags diff --git a/apps/systemtags/lib/Activity/Extension.php b/apps/systemtags/lib/Activity/Extension.php new file mode 100644 index 00000000000..8c101a6f550 --- /dev/null +++ b/apps/systemtags/lib/Activity/Extension.php @@ -0,0 +1,335 @@ + + * + * @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 + * + */ + +namespace OCA\SystemTags\Activity; + +use OCP\Activity\IExtension; +use OCP\Activity\IManager; +use OCP\IL10N; +use OCP\L10N\IFactory; + +/** + * Class Extension + * + * @package OCA\SystemTags\Activity + */ +class Extension implements IExtension { + const APP_NAME = 'systemtags'; + + const CREATE_TAG = 'create_tag'; + const UPDATE_TAG = 'update_tag'; + const DELETE_TAG = 'delete_tag'; + + const ASSIGN_TAG = 'assign_tag'; + const UNASSIGN_TAG = 'unassign_tag'; + + /** @var IFactory */ + protected $languageFactory; + + /** @var IManager */ + protected $activityManager; + + /** + * @param IFactory $languageFactory + * @param IManager $activityManager + */ + public function __construct(IFactory $languageFactory, IManager $activityManager) { + $this->languageFactory = $languageFactory; + $this->activityManager = $activityManager; + } + + protected function getL10N($languageCode = null) { + return $this->languageFactory->get(self::APP_NAME, $languageCode); + } + + /** + * The extension can return an array of additional notification types. + * If no additional types are to be added false is to be returned + * + * @param string $languageCode + * @return array|false + */ + public function getNotificationTypes($languageCode) { + $l = $this->getL10N($languageCode); + + return array( + self::APP_NAME => (string) $l->t('System tags for a file have been modified'), + ); + } + + /** + * For a given method additional types to be displayed in the settings can be returned. + * In case no additional types are to be added false is to be returned. + * + * @param string $method + * @return array|false + */ + public function getDefaultTypes($method) { + return $method === self::METHOD_STREAM ? [self::APP_NAME] : false; + } + + /** + * A string naming the css class for the icon to be used can be returned. + * If no icon is known for the given type false is to be returned. + * + * @param string $type + * @return string|false + */ + public function getTypeIcon($type) { + switch ($type) { + case self::APP_NAME: + return false; + } + + return false; + } + + /** + * The extension can translate a given message to the requested languages. + * If no translation is available false is to be returned. + * + * @param string $app + * @param string $text + * @param array $params + * @param boolean $stripPath + * @param boolean $highlightParams + * @param string $languageCode + * @return string|false + */ + public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { + if ($app !== self::APP_NAME) { + return false; + } + + $l = $this->getL10N($languageCode); + + if ($this->activityManager->isFormattingFilteredObject()) { + $translation = $this->translateShort($text, $l, $params); + if ($translation !== false) { + return $translation; + } + } + + return $this->translateLong($text, $l, $params); + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateShort($text, IL10N $l, array $params) { + + switch ($text) { + case self::ASSIGN_TAG: + $params[2] = $this->convertParameterToTag($params[2], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You assigned system tag %3$s', $params); + } + return (string) $l->t('%1$s assigned system tag %3$s', $params); + case self::UNASSIGN_TAG: + $params[2] = $this->convertParameterToTag($params[2], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You unassigned system tag %3$s', $params); + } + return (string) $l->t('%1$s unassigned system tag %3$s', $params); + } + + return false; + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateLong($text, IL10N $l, array $params) { + + switch ($text) { + case self::CREATE_TAG: + $params[1] = $this->convertParameterToTag($params[1], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You created system tag %2$s', $params); + } + return (string) $l->t('%1$s created system tag %2$s', $params); + case self::DELETE_TAG: + $params[1] = $this->convertParameterToTag($params[1], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You deleted system tag %2$s', $params); + } + return (string) $l->t('%1$s deleted system tag %2$s', $params); + case self::UPDATE_TAG: + $params[1] = $this->convertParameterToTag($params[1], $l); + $params[2] = $this->convertParameterToTag($params[2], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You updated system tag %3$s to %2$s', $params); + } + return (string) $l->t('%1$s updated system tag %3$s to %2$s', $params); + case self::ASSIGN_TAG: + $params[2] = $this->convertParameterToTag($params[2], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You assigned system tag %3$s to %2$s', $params); + } + return (string) $l->t('%1$s assigned system tag %3$s to %2$s', $params); + case self::UNASSIGN_TAG: + $params[2] = $this->convertParameterToTag($params[2], $l); + if ($this->actorIsCurrentUser($params[0])) { + return (string) $l->t('You unassigned system tag %3$s from %2$s', $params); + } + return (string) $l->t('%1$s unassigned system tag %3$s from %2$s', $params); + } + + return false; + } + + /** + * Check if the author is the current user + * + * @param string $user Parameter e.g. `admin` + * @return bool + */ + protected function actorIsCurrentUser($user) { + try { + return strip_tags($user) === $this->activityManager->getCurrentUserId(); + } catch (\UnexpectedValueException $e) { + return false; + } + } + + /** + * The extension can define the type of parameters for translation + * + * Currently known types are: + * * file => will strip away the path of the file and add a tooltip with it + * * username => will add the avatar of the user + * + * @param string $app + * @param string $text + * @return array|false + */ + public function getSpecialParameterList($app, $text) { + if ($app === self::APP_NAME) { + switch ($text) { + case self::CREATE_TAG: + case self::DELETE_TAG: + return array( + 0 => 'username', + //1 => 'systemtag description', + ); + case self::UPDATE_TAG: + return array( + 0 => 'username', + //1 => 'systemtag description', + //2 => 'systemtag description', + ); + + case self::ASSIGN_TAG: + case self::UNASSIGN_TAG: + return array( + 0 => 'username', + 1 => 'file', + //2 => 'systemtag description', + ); + } + } + + return false; + } + + /** + * The extension can define the parameter grouping by returning the index as integer. + * In case no grouping is required false is to be returned. + * + * @param array $activity + * @return integer|false + */ + public function getGroupParameter($activity) { + return false; + } + + /** + * The extension can define additional navigation entries. The array returned has to contain two keys 'top' + * and 'apps' which hold arrays with the relevant entries. + * If no further entries are to be added false is no be returned. + * + * @return array|false + */ + public function getNavigation() { + return false; + } + + /** + * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. + * + * @param string $filterValue + * @return boolean + */ + public function isFilterValid($filterValue) { + return false; + } + + /** + * The extension can filter the types based on the filter if required. + * In case no filter is to be applied false is to be returned unchanged. + * + * @param array $types + * @param string $filter + * @return array|false + */ + public function filterNotificationTypes($types, $filter) { + return false; + } + + /** + * For a given filter the extension can specify the sql query conditions including parameters for that query. + * In case the extension does not know the filter false is to be returned. + * The query condition and the parameters are to be returned as array with two elements. + * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); + * + * @param string $filter + * @return array|false + */ + public function getQueryForFilter($filter) { + return false; + } + + /** + * @param string $parameter + * @param IL10N $l + * @return string + */ + protected function convertParameterToTag($parameter, IL10N $l) { + if (preg_match('/^\\{\{\{(.*)\|\|\|(.*)\}\}\}\<\/parameter\>$/', $parameter, $matches)) { + switch ($matches[2]) { + case 'assignable': + return '' . $matches[1] . ''; + case 'not-assignable': + return '' . $l->t('%s (not-assignable)', $matches[1]) . ''; + case 'invisible': + return '' . $l->t('%s (invisible)', $matches[1]) . ''; + } + } + + return $parameter; + } +} diff --git a/apps/systemtags/lib/Activity/Listener.php b/apps/systemtags/lib/Activity/Listener.php new file mode 100644 index 00000000000..9b6597119c6 --- /dev/null +++ b/apps/systemtags/lib/Activity/Listener.php @@ -0,0 +1,223 @@ + + * + * @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 + * + */ + +namespace OCA\SystemTags\Activity; + +use OCP\Activity\IManager; +use OCP\App\IAppManager; +use OCP\Files\Config\IMountProviderCollection; +use OCP\Files\IRootFolder; +use OCP\Files\Node; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserSession; +use OCP\Share; +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ManagerEvent; +use OCP\SystemTag\MapperEvent; +use OCP\SystemTag\TagNotFoundException; + +class Listener { + /** @var IGroupManager */ + protected $groupManager; + /** @var IManager */ + protected $activityManager; + /** @var IUserSession */ + protected $session; + /** @var \OCP\SystemTag\ISystemTagManager */ + protected $tagManager; + /** @var \OCP\App\IAppManager */ + protected $appManager; + /** @var \OCP\Files\Config\IMountProviderCollection */ + protected $mountCollection; + /** @var \OCP\Files\IRootFolder */ + protected $rootFolder; + + /** + * Listener constructor. + * + * @param IGroupManager $groupManager + * @param IManager $activityManager + * @param IUserSession $session + * @param ISystemTagManager $tagManager + * @param IAppManager $appManager + * @param IMountProviderCollection $mountCollection + * @param IRootFolder $rootFolder + */ + public function __construct(IGroupManager $groupManager, + IManager $activityManager, + IUserSession $session, + ISystemTagManager $tagManager, + IAppManager $appManager, + IMountProviderCollection $mountCollection, + IRootFolder $rootFolder) { + $this->groupManager = $groupManager; + $this->activityManager = $activityManager; + $this->session = $session; + $this->tagManager = $tagManager; + $this->appManager = $appManager; + $this->mountCollection = $mountCollection; + $this->rootFolder = $rootFolder; + } + + /** + * @param ManagerEvent $event + */ + public function event(ManagerEvent $event) { + $actor = $this->session->getUser(); + if ($actor instanceof IUser) { + $actor = $actor->getUID(); + } else { + $actor = ''; + } + + $activity = $this->activityManager->generateEvent(); + $activity->setApp(Extension::APP_NAME) + ->setType(Extension::APP_NAME) + ->setAuthor($actor); + if ($event->getEvent() === ManagerEvent::EVENT_CREATE) { + $activity->setSubject(Extension::CREATE_TAG, [ + $actor, + $this->prepareTagAsParameter($event->getTag()), + ]); + } else if ($event->getEvent() === ManagerEvent::EVENT_UPDATE) { + $activity->setSubject(Extension::UPDATE_TAG, [ + $actor, + $this->prepareTagAsParameter($event->getTag()), + $this->prepareTagAsParameter($event->getTagBefore()), + ]); + } else if ($event->getEvent() === ManagerEvent::EVENT_DELETE) { + $activity->setSubject(Extension::DELETE_TAG, [ + $actor, + $this->prepareTagAsParameter($event->getTag()), + ]); + } else { + return; + } + + $group = $this->groupManager->get('admin'); + if ($group instanceof IGroup) { + foreach ($group->getUsers() as $user) { + $activity->setAffectedUser($user->getUID()); + $this->activityManager->publish($activity); + } + } + } + + /** + * @param MapperEvent $event + */ + public function mapperEvent(MapperEvent $event) { + $tagIds = $event->getTags(); + if ($event->getObjectType() !== 'files' ||empty($tagIds) + || !in_array($event->getEvent(), [MapperEvent::EVENT_ASSIGN, MapperEvent::EVENT_UNASSIGN]) + || !$this->appManager->isInstalled('activity')) { + // System tags not for files, no tags, not (un-)assigning or no activity-app enabled (save the energy) + return; + } + + try { + $tags = $this->tagManager->getTagsByIds($tagIds); + } catch (TagNotFoundException $e) { + // User assigned/unassigned a non-existing tag, ignore... + return; + } + + if (empty($tags)) { + return; + } + + // Get all mount point owners + $cache = $this->mountCollection->getMountCache(); + $mounts = $cache->getMountsForFileId($event->getObjectId()); + if (empty($mounts)) { + return; + } + + $users = []; + foreach ($mounts as $mount) { + $owner = $mount->getUser()->getUID(); + $ownerFolder = $this->rootFolder->getUserFolder($owner); + $nodes = $ownerFolder->getById($event->getObjectId()); + if (!empty($nodes)) { + /** @var Node $node */ + $node = array_shift($nodes); + $path = $node->getPath(); + if (strpos($path, '/' . $owner . '/files/') === 0) { + $path = substr($path, strlen('/' . $owner . '/files')); + } + // Get all users that have access to the mount point + $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true)); + } + } + + $actor = $this->session->getUser(); + if ($actor instanceof IUser) { + $actor = $actor->getUID(); + } else { + $actor = ''; + } + + $activity = $this->activityManager->generateEvent(); + $activity->setApp(Extension::APP_NAME) + ->setType(Extension::APP_NAME) + ->setAuthor($actor) + ->setObject($event->getObjectType(), $event->getObjectId()); + + foreach ($users as $user => $path) { + $activity->setAffectedUser($user); + + foreach ($tags as $tag) { + if ($event->getEvent() === MapperEvent::EVENT_ASSIGN) { + $activity->setSubject(Extension::ASSIGN_TAG, [ + $actor, + $path, + $this->prepareTagAsParameter($tag), + ]); + } else if ($event->getEvent() === MapperEvent::EVENT_UNASSIGN) { + $activity->setSubject(Extension::UNASSIGN_TAG, [ + $actor, + $path, + $this->prepareTagAsParameter($tag), + ]); + } + + $this->activityManager->publish($activity); + } + } + } + + /** + * @param ISystemTag $tag + * @return string + */ + protected function prepareTagAsParameter(ISystemTag $tag) { + if (!$tag->isUserVisible()) { + return '{{{' . $tag->getName() . '|||invisible}}}'; + } else if (!$tag->isUserAssignable()) { + return '{{{' . $tag->getName() . '|||not-assignable}}}'; + } else { + return '{{{' . $tag->getName() . '|||assignable}}}'; + } + } +} diff --git a/apps/updatenotification/appinfo/application.php b/apps/updatenotification/appinfo/application.php deleted file mode 100644 index 08ff4abf766..00000000000 --- a/apps/updatenotification/appinfo/application.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\UpdateNotification\AppInfo; - -use OC\AppFramework\Utility\TimeFactory; -use OC\Updater; -use OCA\UpdateNotification\Controller\AdminController; -use OCA\UpdateNotification\UpdateChecker; -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) { - $updater = new \OC\Updater\VersionCheck( - \OC::$server->getHTTPClientService(), - \OC::$server->getConfig() - ); - return new AdminController( - $c->query('AppName'), - $c->query('Request'), - $c->getServer()->getJobList(), - $c->getServer()->getSecureRandom(), - $c->getServer()->getConfig(), - new TimeFactory(), - $c->getServer()->getL10N($c->query('AppName')), - new UpdateChecker($updater), - $c->getServer()->getDateTimeFormatter() - ); - }); - } - -} diff --git a/apps/updatenotification/appinfo/info.xml b/apps/updatenotification/appinfo/info.xml index 9fbfa8e96b5..5d7a647fd03 100644 --- a/apps/updatenotification/appinfo/info.xml +++ b/apps/updatenotification/appinfo/info.xml @@ -6,6 +6,7 @@ AGPL Lukas Reschke 0.2.0 + UpdateNotification diff --git a/apps/updatenotification/appinfo/routes.php b/apps/updatenotification/appinfo/routes.php index 9021d381b1b..a8890afc59f 100644 --- a/apps/updatenotification/appinfo/routes.php +++ b/apps/updatenotification/appinfo/routes.php @@ -19,7 +19,7 @@ * */ -namespace OCA\UpdateNotification\AppInfo; +use OCA\UpdateNotification\AppInfo\Application; $application = new Application(); $application->registerRoutes($this, ['routes' => [ diff --git a/apps/updatenotification/controller/admincontroller.php b/apps/updatenotification/controller/admincontroller.php deleted file mode 100644 index 5dbcc685809..00000000000 --- a/apps/updatenotification/controller/admincontroller.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\UpdateNotification\Controller; - -use OCA\UpdateNotification\UpdateChecker; -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\IDateTimeFormatter; -use OCP\IL10N; -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; - /** @var UpdateChecker */ - private $updateChecker; - /** @var IL10N */ - private $l10n; - /** @var IDateTimeFormatter */ - private $dateTimeFormatter; - - /** - * @param string $appName - * @param IRequest $request - * @param IJobList $jobList - * @param ISecureRandom $secureRandom - * @param IConfig $config - * @param ITimeFactory $timeFactory - * @param IL10N $l10n - * @param UpdateChecker $updateChecker - * @param IDateTimeFormatter $dateTimeFormatter - */ - public function __construct($appName, - IRequest $request, - IJobList $jobList, - ISecureRandom $secureRandom, - IConfig $config, - ITimeFactory $timeFactory, - IL10N $l10n, - UpdateChecker $updateChecker, - IDateTimeFormatter $dateTimeFormatter) { - parent::__construct($appName, $request); - $this->jobList = $jobList; - $this->secureRandom = $secureRandom; - $this->config = $config; - $this->timeFactory = $timeFactory; - $this->l10n = $l10n; - $this->updateChecker = $updateChecker; - $this->dateTimeFormatter = $dateTimeFormatter; - } - - /** - * @return TemplateResponse - */ - public function displayPanel() { - $lastUpdateCheck = $this->dateTimeFormatter->formatDateTime( - $this->config->getAppValue('core', 'lastupdatedat') - ); - - $channels = [ - 'daily', - 'beta', - 'stable', - 'production', - ]; - $currentChannel = \OCP\Util::getChannel(); - - // Remove the currently used channel from the channels list - if(($key = array_search($currentChannel, $channels)) !== false) { - unset($channels[$key]); - } - $updateState = $this->updateChecker->getUpdateState(); - $params = [ - 'isNewVersionAvailable' => ($updateState === []) ? false : true, - 'lastChecked' => $lastUpdateCheck, - 'currentChannel' => $currentChannel, - 'channels' => $channels, - 'newVersionString' => ($updateState === []) ? '' : $updateState['updateVersion'], - ]; - - return new TemplateResponse($this->appName, 'admin', $params, ''); - } - - /** - * @UseSession - * - * @param string $channel - * @return DataResponse - */ - public function setChannel($channel) { - \OCP\Util::setChannel($channel); - $this->config->setAppValue('core', 'lastupdatedat', 0); - return new DataResponse(['status' => 'success', 'data' => ['message' => $this->l10n->t('Updated channel')]]); - } - - /** - * @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(64); - $this->config->setSystemValue('updater.secret', password_hash($newToken, PASSWORD_DEFAULT)); - - return new DataResponse($newToken); - } -} diff --git a/apps/updatenotification/lib/AppInfo/Application.php b/apps/updatenotification/lib/AppInfo/Application.php new file mode 100644 index 00000000000..08ff4abf766 --- /dev/null +++ b/apps/updatenotification/lib/AppInfo/Application.php @@ -0,0 +1,55 @@ + + * + * @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 + * + */ + +namespace OCA\UpdateNotification\AppInfo; + +use OC\AppFramework\Utility\TimeFactory; +use OC\Updater; +use OCA\UpdateNotification\Controller\AdminController; +use OCA\UpdateNotification\UpdateChecker; +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) { + $updater = new \OC\Updater\VersionCheck( + \OC::$server->getHTTPClientService(), + \OC::$server->getConfig() + ); + return new AdminController( + $c->query('AppName'), + $c->query('Request'), + $c->getServer()->getJobList(), + $c->getServer()->getSecureRandom(), + $c->getServer()->getConfig(), + new TimeFactory(), + $c->getServer()->getL10N($c->query('AppName')), + new UpdateChecker($updater), + $c->getServer()->getDateTimeFormatter() + ); + }); + } + +} diff --git a/apps/updatenotification/lib/Controller/AdminController.php b/apps/updatenotification/lib/Controller/AdminController.php new file mode 100644 index 00000000000..5dbcc685809 --- /dev/null +++ b/apps/updatenotification/lib/Controller/AdminController.php @@ -0,0 +1,140 @@ + + * + * @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 + * + */ + +namespace OCA\UpdateNotification\Controller; + +use OCA\UpdateNotification\UpdateChecker; +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\IDateTimeFormatter; +use OCP\IL10N; +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; + /** @var UpdateChecker */ + private $updateChecker; + /** @var IL10N */ + private $l10n; + /** @var IDateTimeFormatter */ + private $dateTimeFormatter; + + /** + * @param string $appName + * @param IRequest $request + * @param IJobList $jobList + * @param ISecureRandom $secureRandom + * @param IConfig $config + * @param ITimeFactory $timeFactory + * @param IL10N $l10n + * @param UpdateChecker $updateChecker + * @param IDateTimeFormatter $dateTimeFormatter + */ + public function __construct($appName, + IRequest $request, + IJobList $jobList, + ISecureRandom $secureRandom, + IConfig $config, + ITimeFactory $timeFactory, + IL10N $l10n, + UpdateChecker $updateChecker, + IDateTimeFormatter $dateTimeFormatter) { + parent::__construct($appName, $request); + $this->jobList = $jobList; + $this->secureRandom = $secureRandom; + $this->config = $config; + $this->timeFactory = $timeFactory; + $this->l10n = $l10n; + $this->updateChecker = $updateChecker; + $this->dateTimeFormatter = $dateTimeFormatter; + } + + /** + * @return TemplateResponse + */ + public function displayPanel() { + $lastUpdateCheck = $this->dateTimeFormatter->formatDateTime( + $this->config->getAppValue('core', 'lastupdatedat') + ); + + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + $updateState = $this->updateChecker->getUpdateState(); + $params = [ + 'isNewVersionAvailable' => ($updateState === []) ? false : true, + 'lastChecked' => $lastUpdateCheck, + 'currentChannel' => $currentChannel, + 'channels' => $channels, + 'newVersionString' => ($updateState === []) ? '' : $updateState['updateVersion'], + ]; + + return new TemplateResponse($this->appName, 'admin', $params, ''); + } + + /** + * @UseSession + * + * @param string $channel + * @return DataResponse + */ + public function setChannel($channel) { + \OCP\Util::setChannel($channel); + $this->config->setAppValue('core', 'lastupdatedat', 0); + return new DataResponse(['status' => 'success', 'data' => ['message' => $this->l10n->t('Updated channel')]]); + } + + /** + * @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(64); + $this->config->setSystemValue('updater.secret', password_hash($newToken, PASSWORD_DEFAULT)); + + return new DataResponse($newToken); + } +} diff --git a/apps/updatenotification/lib/ResetTokenBackgroundJob.php b/apps/updatenotification/lib/ResetTokenBackgroundJob.php new file mode 100644 index 00000000000..61bd9fc0490 --- /dev/null +++ b/apps/updatenotification/lib/ResetTokenBackgroundJob.php @@ -0,0 +1,76 @@ + + * + * @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 + * + */ + +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) { + // Delete old tokens after 2 days + if($this->timeFactory->getTime() - $this->config->getAppValue('core', 'updater.secret.created', $this->timeFactory->getTime()) >= 172800) { + $this->config->deleteSystemValue('updater.secret'); + } + } + +} diff --git a/apps/updatenotification/lib/UpdateChecker.php b/apps/updatenotification/lib/UpdateChecker.php new file mode 100644 index 00000000000..bf653c23b8f --- /dev/null +++ b/apps/updatenotification/lib/UpdateChecker.php @@ -0,0 +1,67 @@ + + * + * @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 + * + */ + +namespace OCA\UpdateNotification; + +use OC\Updater\VersionCheck; + +class UpdateChecker { + /** @var VersionCheck */ + private $updater; + + /** + * @param VersionCheck $updater + */ + public function __construct(VersionCheck $updater) { + $this->updater = $updater; + } + + /** + * @return array + */ + public function getUpdateState() { + $data = $this->updater->check(); + $result = []; + + if(isset($data['version']) && $data['version'] !== '' && $data['version'] !== []) { + $result['updateAvailable'] = true; + $result['updateVersion'] = $data['versionstring']; + if(substr($data['web'], 0, 8) === 'https://') { + $result['updateLink'] = $data['web']; + } + + return $result; + } + + return []; + } + + /** + * @param array $data + */ + public function getJavaScript(array $data) { + $data['array']['oc_updateState'] = json_encode([ + 'updateAvailable' => true, + 'updateVersion' => $this->getUpdateState()['updateVersion'], + 'updateLink' => isset($this->getUpdateState()['updateLink']) ? $this->getUpdateState()['updateLink'] : '', + ]); + } +} diff --git a/apps/updatenotification/lib/resettokenbackgroundjob.php b/apps/updatenotification/lib/resettokenbackgroundjob.php deleted file mode 100644 index 61bd9fc0490..00000000000 --- a/apps/updatenotification/lib/resettokenbackgroundjob.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * @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 - * - */ - -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) { - // Delete old tokens after 2 days - if($this->timeFactory->getTime() - $this->config->getAppValue('core', 'updater.secret.created', $this->timeFactory->getTime()) >= 172800) { - $this->config->deleteSystemValue('updater.secret'); - } - } - -} diff --git a/apps/updatenotification/lib/updatechecker.php b/apps/updatenotification/lib/updatechecker.php deleted file mode 100644 index bf653c23b8f..00000000000 --- a/apps/updatenotification/lib/updatechecker.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\UpdateNotification; - -use OC\Updater\VersionCheck; - -class UpdateChecker { - /** @var VersionCheck */ - private $updater; - - /** - * @param VersionCheck $updater - */ - public function __construct(VersionCheck $updater) { - $this->updater = $updater; - } - - /** - * @return array - */ - public function getUpdateState() { - $data = $this->updater->check(); - $result = []; - - if(isset($data['version']) && $data['version'] !== '' && $data['version'] !== []) { - $result['updateAvailable'] = true; - $result['updateVersion'] = $data['versionstring']; - if(substr($data['web'], 0, 8) === 'https://') { - $result['updateLink'] = $data['web']; - } - - return $result; - } - - return []; - } - - /** - * @param array $data - */ - public function getJavaScript(array $data) { - $data['array']['oc_updateState'] = json_encode([ - 'updateAvailable' => true, - 'updateVersion' => $this->getUpdateState()['updateVersion'], - 'updateLink' => isset($this->getUpdateState()['updateLink']) ? $this->getUpdateState()['updateLink'] : '', - ]); - } -} diff --git a/apps/updatenotification/tests/Controller/AdminControllerTest.php b/apps/updatenotification/tests/Controller/AdminControllerTest.php new file mode 100644 index 00000000000..d8fc2dd335c --- /dev/null +++ b/apps/updatenotification/tests/Controller/AdminControllerTest.php @@ -0,0 +1,192 @@ + + * + * @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 + * + */ + +namespace OCA\UpdateNotification\Tests\Controller; + +use OCA\UpdateNotification\Controller\AdminController; +use OCA\UpdateNotification\UpdateChecker; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\IJobList; +use OCP\IConfig; +use OCP\IDateTimeFormatter; +use OCP\IL10N; +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; + /** @var IL10N */ + private $l10n; + /** @var UpdateChecker */ + private $updateChecker; + /** @var IDateTimeFormatter */ + private $dateTimeFormatter; + + 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->l10n = $this->getMock('\\OCP\\IL10N'); + $this->updateChecker = $this->getMockBuilder('\\OCA\\UpdateNotification\\UpdateChecker') + ->disableOriginalConstructor()->getMock(); + $this->dateTimeFormatter = $this->getMock('\\OCP\\IDateTimeFormatter'); + + $this->adminController = new AdminController( + 'updatenotification', + $this->request, + $this->jobList, + $this->secureRandom, + $this->config, + $this->timeFactory, + $this->l10n, + $this->updateChecker, + $this->dateTimeFormatter + ); + } + + public function testDisplayPanelWithUpdate() { + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->willReturn('12345'); + $this->dateTimeFormatter + ->expects($this->once()) + ->method('formatDateTime') + ->with('12345') + ->willReturn('LastCheckedReturnValue'); + $this->updateChecker + ->expects($this->once()) + ->method('getUpdateState') + ->willReturn(['updateVersion' => '8.1.2']); + + $params = [ + 'isNewVersionAvailable' => true, + 'lastChecked' => 'LastCheckedReturnValue', + 'currentChannel' => \OCP\Util::getChannel(), + 'channels' => $channels, + 'newVersionString' => '8.1.2', + ]; + + $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); + $this->assertEquals($expected, $this->adminController->displayPanel()); + } + + public function testDisplayPanelWithoutUpdate() { + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->willReturn('12345'); + $this->dateTimeFormatter + ->expects($this->once()) + ->method('formatDateTime') + ->with('12345') + ->willReturn('LastCheckedReturnValue'); + $this->updateChecker + ->expects($this->once()) + ->method('getUpdateState') + ->willReturn([]); + + $params = [ + 'isNewVersionAvailable' => false, + 'lastChecked' => 'LastCheckedReturnValue', + 'currentChannel' => \OCP\Util::getChannel(), + 'channels' => $channels, + 'newVersionString' => '', + ]; + + $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); + $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(64) + ->willReturn('MyGeneratedToken'); + $this->config + ->expects($this->once()) + ->method('setSystemValue') + ->with('updater.secret'); + $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()); + } +} diff --git a/apps/updatenotification/tests/controller/AdminControllerTest.php b/apps/updatenotification/tests/controller/AdminControllerTest.php deleted file mode 100644 index d8fc2dd335c..00000000000 --- a/apps/updatenotification/tests/controller/AdminControllerTest.php +++ /dev/null @@ -1,192 +0,0 @@ - - * - * @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 - * - */ - -namespace OCA\UpdateNotification\Tests\Controller; - -use OCA\UpdateNotification\Controller\AdminController; -use OCA\UpdateNotification\UpdateChecker; -use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\TemplateResponse; -use OCP\AppFramework\Utility\ITimeFactory; -use OCP\BackgroundJob\IJobList; -use OCP\IConfig; -use OCP\IDateTimeFormatter; -use OCP\IL10N; -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; - /** @var IL10N */ - private $l10n; - /** @var UpdateChecker */ - private $updateChecker; - /** @var IDateTimeFormatter */ - private $dateTimeFormatter; - - 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->l10n = $this->getMock('\\OCP\\IL10N'); - $this->updateChecker = $this->getMockBuilder('\\OCA\\UpdateNotification\\UpdateChecker') - ->disableOriginalConstructor()->getMock(); - $this->dateTimeFormatter = $this->getMock('\\OCP\\IDateTimeFormatter'); - - $this->adminController = new AdminController( - 'updatenotification', - $this->request, - $this->jobList, - $this->secureRandom, - $this->config, - $this->timeFactory, - $this->l10n, - $this->updateChecker, - $this->dateTimeFormatter - ); - } - - public function testDisplayPanelWithUpdate() { - $channels = [ - 'daily', - 'beta', - 'stable', - 'production', - ]; - $currentChannel = \OCP\Util::getChannel(); - - // Remove the currently used channel from the channels list - if(($key = array_search($currentChannel, $channels)) !== false) { - unset($channels[$key]); - } - - $this->config - ->expects($this->once()) - ->method('getAppValue') - ->with('core', 'lastupdatedat') - ->willReturn('12345'); - $this->dateTimeFormatter - ->expects($this->once()) - ->method('formatDateTime') - ->with('12345') - ->willReturn('LastCheckedReturnValue'); - $this->updateChecker - ->expects($this->once()) - ->method('getUpdateState') - ->willReturn(['updateVersion' => '8.1.2']); - - $params = [ - 'isNewVersionAvailable' => true, - 'lastChecked' => 'LastCheckedReturnValue', - 'currentChannel' => \OCP\Util::getChannel(), - 'channels' => $channels, - 'newVersionString' => '8.1.2', - ]; - - $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); - $this->assertEquals($expected, $this->adminController->displayPanel()); - } - - public function testDisplayPanelWithoutUpdate() { - $channels = [ - 'daily', - 'beta', - 'stable', - 'production', - ]; - $currentChannel = \OCP\Util::getChannel(); - - // Remove the currently used channel from the channels list - if(($key = array_search($currentChannel, $channels)) !== false) { - unset($channels[$key]); - } - - $this->config - ->expects($this->once()) - ->method('getAppValue') - ->with('core', 'lastupdatedat') - ->willReturn('12345'); - $this->dateTimeFormatter - ->expects($this->once()) - ->method('formatDateTime') - ->with('12345') - ->willReturn('LastCheckedReturnValue'); - $this->updateChecker - ->expects($this->once()) - ->method('getUpdateState') - ->willReturn([]); - - $params = [ - 'isNewVersionAvailable' => false, - 'lastChecked' => 'LastCheckedReturnValue', - 'currentChannel' => \OCP\Util::getChannel(), - 'channels' => $channels, - 'newVersionString' => '', - ]; - - $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); - $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(64) - ->willReturn('MyGeneratedToken'); - $this->config - ->expects($this->once()) - ->method('setSystemValue') - ->with('updater.secret'); - $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()); - } -} -- cgit v1.2.3