From 8bf378800c4080605c751e658887518285e735d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Gomes=20da=20Silva=20Lisboa?= Date: Mon, 11 Dec 2017 11:03:23 -0200 Subject: [PATCH] Enable audit by configuration #163 - audit of following actions: - user X created circle Z; - user X removed circle Z; - user X change name of circle Z for circle W; - user X was added to circle U by user Z; - user X shared file/folder with circle Y; - user X, that created circle, unshared file/folder with circle Y - member X accepted invitation to circle Y by user Z; - member X left circle Y; - user X change role of member Y in circle Z for W. - user X was invited to circle U by user Z - adjust circles to emit signals of sharing to activity --- l10n/pt_BR.js | 6 +- l10n/pt_BR.json | 6 +- lib/Activity/Consumer.php | 93 ++++++++++++++++++++ lib/Activity/Provider.php | 30 ++++++- lib/Activity/ProviderParser.php | 6 +- lib/Activity/ProviderSubjectShared.php | 109 +++++++++++++++++++++++ lib/Api/v1/Circles.php | 32 +++++++ lib/AppInfo/Application.php | 20 ++++- lib/Events/UserEvents.php | 116 ++++++++++++++++++++++++- lib/Hooks/UserHooks.php | 11 ++- lib/Model/BaseMember.php | 36 +++++--- lib/Service/BaseService.php | 47 ++++++++++ lib/Service/CirclesService.php | 41 ++++++++- lib/Service/MembersService.php | 22 ++++- lib/ShareByCircleProvider.php | 82 ++++++++++++++++- 15 files changed, 621 insertions(+), 36 deletions(-) create mode 100644 lib/Activity/Consumer.php create mode 100644 lib/Activity/ProviderSubjectShared.php create mode 100644 lib/Service/BaseService.php diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js index f6f8970d6..86c006870 100644 --- a/l10n/pt_BR.js +++ b/l10n/pt_BR.js @@ -279,6 +279,10 @@ OC.L10N.register( "Members limit:" : "Limite de membros:", "Default limit to the number of members in a circle." : "Limite de membros em um círculo.", "Allow linking of groups:" : "Permitir links dos grupos:", - "Allow federated circles:" : "Permitir círculos federados:" + "Allow federated circles:" : "Permitir círculos federados:", + "You shared {file} with circle {circle}" : "Você compartilhou {file} com o círculo {circle}", + "{author} shared {file} with the circle {circle}" : "{author} compartilhou {file} com o círculo {circle}", + "You unshared {file} with the circle {circle}" : "Você descompartilhou {file} com o círculo {circle}", + "{author} unshared {file} with the circle {circle}" : "{author} descompartilhou {file} com o círculo {circle}" }, "nplurals=2; plural=(n > 1);"); diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json index 1c0891aa2..787a84c78 100644 --- a/l10n/pt_BR.json +++ b/l10n/pt_BR.json @@ -277,6 +277,10 @@ "Members limit:" : "Limite de membros:", "Default limit to the number of members in a circle." : "Limite de membros em um círculo.", "Allow linking of groups:" : "Permitir links dos grupos:", - "Allow federated circles:" : "Permitir círculos federados:" + "Allow federated circles:" : "Permitir círculos federados:", + "You shared {file} with circle {circle}" : "Você compartilhou {file} com o círculo {circle}", + "{author} shared {file} with the circle {circle}" : "{author} compartilhou {file} com o círculo {circle}", + "You unshared {file} with the circle {circle}" : "Você descompartilhou {file} com o círculo {circle}", + "{author} unshared {file} with the circle {circle}" : "{author} descompartilhou {file} com o círculo {circle}" },"pluralForm" :"nplurals=2; plural=(n > 1);" } \ No newline at end of file diff --git a/lib/Activity/Consumer.php b/lib/Activity/Consumer.php new file mode 100644 index 000000000..b62919412 --- /dev/null +++ b/lib/Activity/Consumer.php @@ -0,0 +1,93 @@ + + * @copyright 2018 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ + +namespace OCA\Circles\Activity; + +use OCP\Activity\IConsumer; +use OCP\Activity\IManager; +use OCA\Activity\Data; +use OCA\Activity\UserSettings; +use OCP\L10N\IFactory; +use OCP\Activity\IEvent; + +class Consumer implements IConsumer { + /** @var Data */ + protected $data; + /** @var IManager */ + protected $manager; + + /** @var UserSettings */ + protected $userSettings; + + /** @var IFactory */ + protected $l10nFactory; + + /** + * Constructor + * + * @param Data $data + * @param IManager $manager + * @param UserSettings $userSettings + * @param IFactory $l10nFactory + */ + public function __construct(Data $data, IManager $manager, UserSettings $userSettings, IFactory $l10nFactory) { + $this->data = $data; + $this->manager = $manager; + $this->userSettings = $userSettings; + $this->l10nFactory = $l10nFactory; + } + + /** + * Send an event to the notifications of a user + * + * @param IEvent $event + * @return null + */ + public function receive(IEvent $event) { + $selfAction = $event->getAffectedUser() === $event->getAuthor(); + $emailSetting = $this->userSettings->getUserSetting($event->getAffectedUser(), 'email', $event->getType()); + $emailSetting = ($emailSetting) ? $this->userSettings->getUserSetting($event->getAffectedUser(), 'setting', 'batchtime') : false; + + // User is not the author or wants to see their own actions + $createStream = !$selfAction || $this->userSettings->getUserSetting($event->getAffectedUser(), 'setting', 'self'); + + // Add activity to stream + try { + $this->data->send($event); + } catch (\Exception $e) { + OC::$server->getLogger()->logException($e); + } + // User is not the author or wants to see their own actions + $createEmail = !$selfAction || $this->userSettings->getUserSetting($event->getAffectedUser(), 'setting', 'selfemail'); + + // Add activity to mail queue + if ($emailSetting !== false && $createEmail) { + $latestSend = $event->getTimestamp() + $emailSetting; + $this->data->storeMail($event, $latestSend); + } + } +} \ No newline at end of file diff --git a/lib/Activity/Provider.php b/lib/Activity/Provider.php index 109e3559a..40a793479 100644 --- a/lib/Activity/Provider.php +++ b/lib/Activity/Provider.php @@ -55,6 +55,9 @@ class Provider implements IProvider { /** @var ProviderSubjectLink */ private $parserLink; + + /** @var ProviderSubjectShared */ + private $parserShared; /** @var MiscService */ protected $miscService; @@ -66,7 +69,7 @@ class Provider implements IProvider { public function __construct( IManager $activityManager, MiscService $miscService, ProviderSubjectCircle $parserCircle, ProviderSubjectMember $parserMember, ProviderSubjectGroup $parserGroup, - ProviderSubjectLink $parserLink + ProviderSubjectLink $parserLink, ProviderSubjectShared $parserShared ) { $this->activityManager = $activityManager; $this->miscService = $miscService; @@ -75,6 +78,7 @@ public function __construct( $this->parserMember = $parserMember; $this->parserGroup = $parserGroup; $this->parserLink = $parserLink; + $this->parserShared = $parserShared; } @@ -92,9 +96,11 @@ public function parse($lang, IEvent $event, IEvent $previousEvent = null) { $this->setIcon($event, $circle); $this->parseAsMember($event, $circle, $params); $this->parseAsModerator($event, $circle, $params); - } catch (FakeException $e) { /** clean exit */ + } catch (InvalidArgumentException $e) { + /** sharing is a special case because app is files **/ + $this->parseShared($event, $params); } return $event; @@ -110,7 +116,7 @@ private function initActivityParser(IEvent $event, $params) { throw new InvalidArgumentException(); } - if (!key_exists('circle', $params)) { + if ($event->getApp() === Application::APP_NAME && !key_exists('circle', $params)) { throw new InvalidArgumentException(); } } @@ -252,5 +258,21 @@ private function parseLinkAsModerator(IEvent &$event, Circle $circle, $params) { $this->parserLink->parseLinkRemove($event, $circle, $remote); } - + /** + * @param IEvent $event + * @param array $params + * + * @throws FakeException + */ + private function parseShared(IEvent &$event, $params) { + if ($event->getSubject() === 'shared_circle_self') { + $this->parserShared->parseSubjectSharedWithCircle($event, $params); + return; + } + if ($event->getSubject() === 'unshared_circle_self') { + $this->parserShared->parseSubjectUnsharedWithCircle($event, $params); + return; + } + throw new InvalidArgumentException(); + } } \ No newline at end of file diff --git a/lib/Activity/ProviderParser.php b/lib/Activity/ProviderParser.php index a01965dc7..fb2c07d39 100644 --- a/lib/Activity/ProviderParser.php +++ b/lib/Activity/ProviderParser.php @@ -99,7 +99,7 @@ protected function parseCircleEvent(IEvent &$event, Circle $circle, $remote, $ow * @param string $line * @param array $data */ - private function setSubject(IEvent $event, $line, $data) { + protected function setSubject(IEvent $event, $line, $data) { $this->setParsedSubject($event, $line, $data); $this->setRichSubject($event, $line, $data); } @@ -110,7 +110,7 @@ private function setSubject(IEvent $event, $line, $data) { * @param string $line * @param array $data */ - private function setRichSubject(IEvent $event, $line, $data) { + protected function setRichSubject(IEvent $event, $line, $data) { $ak = array_keys($data); foreach ($ak as $k) { $subAk = array_keys($data[$k]); @@ -130,7 +130,7 @@ private function setRichSubject(IEvent $event, $line, $data) { * @param string $line * @param array $data */ - private function setParsedSubject(IEvent $event, $line, $data) { + protected function setParsedSubject(IEvent $event, $line, $data) { $ak = array_keys($data); $replace = []; foreach ($ak as $k) { diff --git a/lib/Activity/ProviderSubjectShared.php b/lib/Activity/ProviderSubjectShared.php new file mode 100644 index 000000000..5ef113dc9 --- /dev/null +++ b/lib/Activity/ProviderSubjectShared.php @@ -0,0 +1,109 @@ + + * @copyright 2018 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCA\Circles\Activity; + +use OCA\Circles\Exceptions\FakeException; +use OCA\Circles\Model\Circle; +use OCA\Circles\Model\FederatedLink; +use OCA\Circles\Model\Member; +use OCP\Activity\IEvent; +use OCA\Circles\Api\v1\Circles; + +class ProviderSubjectShared extends ProviderParser { + /** + * @param IEvent $event + * @param array $params + * + * @throws FakeException + */ + public function parseSubjectSharedWithCircle(IEvent &$event, array $params) { + $this->parseSharedEvent( + $event, $params, null, + $this->l10n->t('You shared {file} with circle {circle}'), + $this->l10n->t('{author} shared {file} with the circle {circle}') + ); + } + + /** + * @param IEvent $event + * @param array $params + * + * @throws FakeException + */ + public function parseSubjectUnsharedWithCircle(IEvent &$event, array $params) { + $this->parseSharedEvent( + $event, $params, null, + $this->l10n->t('You unshared {file} with the circle {circle}'), + $this->l10n->t('{author} unshared {file} with the circle {circle}') + ); + } + + /** + * general function to generate Circle event. + * + * @param IEvent $event + * @param array $params + * @param FederatedLink|null $remote + * @param string $ownEvent + * @param string $othersEvent + */ + protected function parseSharedEvent(IEvent &$event, array $params, $remote, $ownEvent, $othersEvent + ) { + $circle = Circles::infoCircleByName($params['circle']['name']); + $path = Circles::getViewPath($params['file']['id']); + + $data = [ + 'author' => [ + 'type' => 'user', + 'id' => $params['author']['id'], + 'name' => $params['author']['name'], + '_parsed' => $params['author']['name'] + ], + 'circle' => [ + 'type' => 'circle', + 'id' => $circle->getId(), + 'name' => $circle->getName(), + '_parsed' => $circle->getName(), + 'link' => Circles::generateLink($circle->getUniqueId()) + ], + 'file' => [ + 'type' => 'file', + 'id' => $params['file']['id'], + 'name' => $params['file']['name'], + 'path' => $path, + 'link' => \OC::$server->getURLGenerator ()->linkToRouteAbsolute('files.view.index', array ( + 'dir' => ($params['file']['type'] !== 'file') ? dirname($path) : $path) ) + ] + ]; + + if ($this->isViewerTheAuthor($circle, $this->activityManager->getCurrentUserId())) { + $this->setSubject($event, $ownEvent, $data); + return; + } + + $this->setSubject($event, $othersEvent, $data); + } +} \ No newline at end of file diff --git a/lib/Api/v1/Circles.php b/lib/Api/v1/Circles.php index 64f4c5970..c4ddd4e84 100644 --- a/lib/Api/v1/Circles.php +++ b/lib/Api/v1/Circles.php @@ -43,6 +43,7 @@ use OCA\Circles\Service\SharingFrameService; use OCP\AppFramework\QueryException; use OCP\Util; +use OC\Files\View; class Circles { @@ -529,4 +530,35 @@ public static function getFilesForCircles($circleUniqueIds) { return $c->query(CirclesService::class) ->getFilesForCircles($circleUniqueIds); } + + /** + * Get a list of objects which are shred with $circleUniqueId. + * + * @since 0.15.0 + * + * @param string $circleName + * + * @return Circle|null + * @throws CircleDoesNotExistException + */ + public static function infoCircleByName($circleName) { + $c = self::getContainer(); + return $c->query(CirclesService::class) + ->infoCircleByName($circleName); + } + + /** + * Get path of a file from id. + * + * @since 0.15.0 + * + * @param string $id + * + * @return string|null + */ + public static function getViewPath($id) { + $c = self::getContainer(); + return $c->query(View::class) + ->getPath($id); + } } \ No newline at end of file diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index bb1d1bb6a..160505b9c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -34,7 +34,7 @@ use OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; use OCP\Util; - +use OCA\Circles\Activity\Consumer; class Application extends App { @@ -70,6 +70,12 @@ public function registerHooks() { Util::connectHook( 'OC_User', 'post_deleteGroup', '\OCA\Circles\Hooks\UserHooks', 'onGroupDeleted' ); + Util::connectHook( + 'OCP\Share', 'post_shared', '\OCA\Circles\Hooks\UserHooks', 'onItemShared' + ); + Util::connectHook( + 'OCP\Share', 'post_unshared', '\OCA\Circles\Hooks\UserHooks', 'onItemUnshared' + ); } @@ -134,6 +140,16 @@ function() { } ); } - + + /** + * + */ + public function registerConsumers() + { + $c = $this->getContainer(); + \OC::$server->getActivityManager()->registerConsumer(function() use ($c){ + return $c->query(Consumer::class); + }); + } } diff --git a/lib/Events/UserEvents.php b/lib/Events/UserEvents.php index 8b8986a94..b87fb6f2d 100644 --- a/lib/Events/UserEvents.php +++ b/lib/Events/UserEvents.php @@ -8,6 +8,10 @@ use OCA\Circles\Service\GroupsService; use OCA\Circles\Service\MembersService; use OCA\Circles\Service\MiscService; +use OCP\IUser; +use OCA\Circles\AppInfo\Application; +use OC\Files\View; +use OCA\Circles\Api\v1\Circles; class UserEvents { @@ -22,6 +26,9 @@ class UserEvents { /** @var MiscService */ private $miscService; + + /** @var IUser */ + private static $user; /** * UserEvents constructor. @@ -59,6 +66,113 @@ public function onGroupDeleted(array $params) { $groupId = $params['gid']; $this->groupsService->onGroupRemoved($groupId); } - + + /** + * + * @param array $params + */ + public function onItemShared(array $params) { + $shareWith = $params['shareWith']; + $fileTarget = $params['fileTarget']; + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("user $user shared $fileTarget with $shareWith"); + try { + $path = Circles::getViewPath($params['nodeId']); + } catch (NotFoundException $e) { + return; + } + $subjectParams = [ + 'author' => [ + 'id' => $this->getUser()->getUID(), + 'name' => $user + ], + 'circle' => [ + 'name' => $shareWith + ], + 'file' => [ + 'id' => $params['nodeId'], + 'name' => $fileTarget, + 'type' => $params['itemType'] + ] + ]; + $objectType = ($params ['id']) ? 'files' : ''; + $link = \OC::$server->getURLGenerator ()->linkToRouteAbsolute('files.view.index', array ( + 'dir' => ($params['itemType'] !== 'file') ? dirname($path) : $path + ) ); + $event = \OC::$server->getActivityManager()->generateEvent('shared'); + $event->setApp('files_sharing') + ->setType('shared') + ->setAffectedUser($this->getUser()->getDisplayName()) + ->setTimestamp(time()) + ->setSubject('shared_circle_self', $subjectParams) + ->setParsedSubject("$user shared $fileTarget with the circle $circle") + ->setObject($objectType,(int) $params ['id'], $fileTarget ) + ->setLink($link); + \OC::$server->getActivityManager()->publish($event); + } + + /** + * + * @param array $params + */ + public function onItemUnshared(array $params) { + $shareWith = $params ['shareWith']; + $fileTarget = $params ['fileTarget']; + $user = $this->getUser ()->getDisplayName (); + if (! empty ( $shareWith )) { + if (ctype_alnum ( $shareWith )) { + try { + $shareWith = $this->circlesService->detailsCircle ( $shareWith )->getName (); + } catch ( \Exception $e ) { + } + } + } + $this->miscService->log ( "user $user unshared $fileTarget with $shareWith"); + try { + $path = Circles::getViewPath($params['nodeId']); + } catch ( NotFoundException $e ) { + return; + } + $subjectParams = [ + 'author' => [ + 'id' => $this->getUser()->getUID(), + 'name' => $user + ], + 'circle' => [ + 'name' => $shareWith + ], + 'file' => [ + 'id' => $params['nodeId'], + 'name' => $fileTarget, + 'type' => $params['itemType'] + ] + ]; + $objectType = ($params ['id']) ? 'files' : ''; + $link = \OC::$server->getURLGenerator ()->linkToRouteAbsolute ( 'files.view.index', array ( + 'dir' => ($params ['itemType'] !== 'file') ? dirname ( $path ) : $path + ) ); + $event = \OC::$server->getActivityManager ()->generateEvent ('shared'); + $event->setApp('files_sharing') + ->setType('shared') + ->setAffectedUser($this->getUser()->getDisplayName()) + ->setTimestamp(time()) + ->setSubject('unshared_circle_self', $subjectParams ) + ->setParsedSubject("$user unshared $fileTarget with the circle $shareWith") + ->setObject($objectType,(int)$params ['id'], $params ['fileTarget']) + ->setLink ( $link ); + \OC::$server->getActivityManager ()->publish ( $event ); + } + + /** + * + * @return User + */ + private function getUser() { + if (self::$user == null) { + $app = new Application(); + self::$user = $app->getContainer()->query('UserSession')->getUser(); + } + return self::$user; + } } diff --git a/lib/Hooks/UserHooks.php b/lib/Hooks/UserHooks.php index eb8e7e6fe..8d2fa5dad 100644 --- a/lib/Hooks/UserHooks.php +++ b/lib/Hooks/UserHooks.php @@ -22,11 +22,18 @@ public static function onUserDeleted($params) { ->onUserDeleted($params); } - public static function onGroupDeleted($params) { self::getController() ->onGroupDeleted($params); } -} + public static function onItemShared($params) { + self::getController() + ->onItemShared($params); + } + public static function onItemUnshared($params) { + self::getController() + ->onItemUnshared($params); + } +} \ No newline at end of file diff --git a/lib/Model/BaseMember.php b/lib/Model/BaseMember.php index a24ecfba1..a30c00484 100644 --- a/lib/Model/BaseMember.php +++ b/lib/Model/BaseMember.php @@ -277,20 +277,7 @@ public function jsonSerialize() { } public function getLevelString() { - switch ($this->getLevel()) { - case self::LEVEL_NONE: - return 'Not a member'; - case self::LEVEL_MEMBER: - return 'Member'; - case self::LEVEL_MODERATOR: - return 'Moderator'; - case self::LEVEL_ADMIN: - return 'Admin'; - case self::LEVEL_OWNER: - return 'Owner'; - } - - return 'none'; + return self::getLevelStringFromCode($this->getLevel()); } @@ -308,4 +295,25 @@ public function getTypeString() { return 'none'; } + + /** + * @param integer $code + * @return string + */ + public static function getLevelStringFromCode($code) { + switch ($code) { + case self::LEVEL_NONE: + return 'Not a member'; + case self::LEVEL_MEMBER: + return 'Member'; + case self::LEVEL_MODERATOR: + return 'Moderator'; + case self::LEVEL_ADMIN: + return 'Admin'; + case self::LEVEL_OWNER: + return 'Owner'; + } + + return 'none'; + } } diff --git a/lib/Service/BaseService.php b/lib/Service/BaseService.php new file mode 100644 index 000000000..7579a6466 --- /dev/null +++ b/lib/Service/BaseService.php @@ -0,0 +1,47 @@ + + * + * @copyright 2018 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ + +namespace OCA\Circles\Service; + +use OCA\Circles\AppInfo\Application; +use OC\User\User; + +abstract class BaseService { + protected static $user = null; + + /** + * @return User + */ + protected function getUser() + { + if (self::$user == null){ + $app = new Application(); + self::$user = $app->getContainer()->query('UserSession')->getUser(); + } + return self::$user; + } +} \ No newline at end of file diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index 2ecf9b098..179e2d927 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -49,8 +49,9 @@ use OCA\Circles\Model\Member; use OCP\IGroupManager; use OCP\IL10N; +use OCP\Util; -class CirclesService { +class CirclesService extends BaseService { /** @var string */ private $userId; @@ -159,6 +160,9 @@ public function createCircle($type, $name) { try { $this->circlesRequest->createCircle($circle, $this->userId); $this->membersRequest->createMember($circle->getOwner()); + + $owner = $circle->getOwner()->getDisplayName(); + $this->miscService->log("user $owner created circle $name"); } catch (CircleAlreadyExistsException $e) { throw $e; } @@ -312,13 +316,20 @@ public function settingsCircle($circleUniqueId, $settings) { } $ak = array_keys($settings); + $changes = ''; foreach ($ak AS $k) { + if (trim($circle->getSetting($k)) !== trim($settings[$k])){ + $changes .= ((empty($changes) ? '' : ' and ') . "$k to {$settings[$k]}"); + } $circle->setSetting($k, $settings[$k]); } $this->circlesRequest->updateCircle($circle, $this->userId); $this->eventsService->onSettingsChange($circle); + + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("user $user updated circle $formerCircleName changing $changes"); } catch (\Exception $e) { throw $e; } @@ -343,6 +354,7 @@ public function joinCircle($circleUniqueId) { $member = $this->membersRequest->getFreshNewMember( $circleUniqueId, $this->userId, Member::TYPE_USER ); + $formerStatus = $member->getStatus(); $member->hasToBeAbleToJoinTheCircle(); $this->checkThatCircleIsNotFull($circle); @@ -350,6 +362,17 @@ public function joinCircle($circleUniqueId) { $this->membersRequest->updateMember($member); $this->eventsService->onMemberNew($circle, $member); + + $circleName = $circle->getName(); + $circleType = $circle->getType(); + $memberName = $member->getDisplayName(); + if ($formerStatus == Member::STATUS_INVITED){ + $this->miscService->log("member $memberName accepted invitation to circle $circleName"); + } else if ($circle->getType() == Circle::CIRCLES_CLOSED) { + $this->miscService->log("member $memberName requested to join circle $circleName"); + } else { + $this->miscService->log("member $memberName joined circle $circleName"); + } } catch (\Exception $e) { throw $e; } @@ -374,11 +397,23 @@ public function leaveCircle($circleUniqueId) { $member->hasToBeMemberOrAlmost(); $member->cantBeOwner(); + $circleName = $circle->getName(); + $formerStatus = $member->getStatus(); + $memberName = $member->getDisplayName(); + $this->eventsService->onMemberLeaving($circle, $member); $this->membersRequest->removeMember($member); $this->sharesRequest->removeSharesFromMember($member); + if ($formerStatus == Member::STATUS_INVITED){ + $this->miscService->log("member $memberName refused invitation to circle $circleName"); + } else if ($circle->getType() == Circle::CIRCLES_CLOSED) { + $this->miscService->log("member $memberName cancelled invitation from circle $circleName"); + } else { + $this->miscService->log("member $memberName left circle $circleName"); + } + return $member; } @@ -402,6 +437,10 @@ public function removeCircle($circleUniqueId) { $this->membersRequest->removeAllFromCircle($circleUniqueId); $this->circlesRequest->destroyCircle($circleUniqueId); + + $circleName = $circle->getName(); + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("user $user destroyed circle $circleName"); } diff --git a/lib/Service/MembersService.php b/lib/Service/MembersService.php index 836eafcfd..4619a9027 100644 --- a/lib/Service/MembersService.php +++ b/lib/Service/MembersService.php @@ -41,8 +41,9 @@ use OCA\Circles\Model\Member; use OCP\IL10N; use OCP\IUserManager; +use OCP\Util; -class MembersService { +class MembersService extends BaseService { /** @var string */ private $userId; @@ -125,10 +126,15 @@ public function addMember($circleUniqueId, $ident, $type) { $circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId); $circle->getHigherViewer() ->hasToBeModerator(); - + if (!$this->addMassiveMembers($circle, $ident, $type)) { $this->addSingleMember($circle, $ident, $type); } + + $action = ($type == Circle::CIRCLES_CLOSED ? 'invited' : 'added'); + $circleName = $circle->getName(); + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("user $user $action member $ident to circle $circleName"); } catch (\Exception $e) { throw $e; } @@ -411,7 +417,12 @@ public function levelMember($circleUniqueId, $name, $type, $level) { $member = $this->membersRequest->forceGetMember($circle->getUniqueId(), $name, $type); $member->levelHasToBeEditable(); $this->updateMemberLevel($circle, $member, $level); - + + $circleName = $circle->getName(); + $levelString = Member::getLevelStringFromCode($level); + $memberName = $member->getDisplayName(); + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("$user changed level of $memberName from circle $circleName to $levelString"); return $this->membersRequest->getMembers( $circle->getUniqueId(), $circle->getHigherViewer() ); @@ -518,6 +529,11 @@ public function removeMember($circleUniqueId, $name, $type) { $circle->getHigherViewer() ->hasToBeHigherLevel($member->getLevel()); + + $user = $this->getUser()->getDisplayName(); + $memberName = $member->getDisplayName(); + $circleName = $circle->getName(); + $this->miscService->log("user $user removed member $memberName from circle $circleName"); } catch (\Exception $e) { throw $e; } diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 57ee8a5b8..b11fffd58 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -59,7 +59,8 @@ use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IShare; use OCP\Share\IShareProvider; - +use OCP\Util; +use OCP\IUser; class ShareByCircleProvider extends CircleProviderRequest implements IShareProvider { @@ -84,7 +85,9 @@ class ShareByCircleProvider extends CircleProviderRequest implements IShareProvi /** @var MembersRequest */ private $membersRequest; - + /** $var IUser */ + private static $user = null; + /** * DefaultShareProvider constructor. * @@ -139,6 +142,8 @@ public function identifier() { * @throws \Exception */ public function create(IShare $share) { + $circle = null; + $shareId = null; try { $nodeId = $share->getNode() ->getId(); @@ -166,8 +171,34 @@ public function create(IShare $share) { '\OCA\Circles\Circles\FileSharingBroadcaster' ); + $user = $this->getUser()->getDisplayName(); + $target = $share->getTarget(); + $shareWith = $share->getSharedWith(); + $this->miscService->log("user $user shared $target with $shareWith"); + if ($this->getShareById($shareId)){ + Util::emitHook('OCP\Share', 'post_shared',[ + 'circle' => $circle->getName(), + 'fileTarget'=> $share->getTarget(), + 'id' => $share->getId(), + 'itemType' => $share->getNodeType(), + 'nodeId' => $share->getNodeId(), + 'shareType' => $share->getShareType(), + 'shareWith' => $circle->getName() + ]); + } return $this->getShareById($shareId); } catch (\Exception $e) { + if ($this->getShareById($shareId)){ + Util::emitHook('OCP\Share', 'post_shared',[ + 'circle' => $circle->getName(), + 'fileTarget'=> $share->getTarget(), + 'id' => $share->getId(), + 'itemType' => $share->getNodeType(), + 'nodeId' => $share->getNodeId(), + 'shareType' => $share->getShareType(), + 'shareWith' => $circle->getName() + ]); + } throw $e; } } @@ -189,7 +220,10 @@ public function update(IShare $share) { ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())); $qb->execute(); - + + $user = $this->getUser()->getDisplayName(); + $target = $share->getTarget(); + $this->miscService->log("user $user updated shared $target"); return $share; } @@ -203,6 +237,18 @@ public function delete(IShare $share) { $qb = $this->getBaseDeleteSql(); $this->limitToShareAndChildren($qb, $share->getId()); + + $user = $this->getUser()->getDisplayName(); + $target = $share->getTarget(); + $shareWith = $share->getSharedWith(); + Util::emitHook('OCP\Share', 'post_unshared',[ + 'fileTarget'=> $target, + 'id' => $share->getId(), + 'itemType' => $share->getNodeType(), + 'nodeId' => $share->getNodeId(), + 'shareType' => $share->getShareType(), + 'shareWith' => $shareWith + ]); $qb->execute(); } @@ -223,8 +269,25 @@ public function deleteFromSelf(IShare $share, $userId) { $this->limitToShare($qb, $childId); $qb->execute(); - } + try { + $shareWith = $this->circlesRequest->getCircle($share->getSharedWith(),$userId)->getName(); + } catch (\Exception $e) { + $shareWith = $share->getSharedWith(); + } + + $target = $share->getTarget(); + $user = $this->getUser()->getDisplayName(); + $this->miscService->log("user $user unshared $target with $shareWith"); + Util::emitHook('OCP\Share', 'post_unshared',[ + 'fileTarget'=> $target, + 'id' => $share->getId(), + 'itemType' => $share->getNodeType(), + 'nodeId' => $share->getNodeId(), + 'shareType' => $share->getShareType(), + 'shareWith' => $shareWith + ]); + } /** * Move a share as a recipient. @@ -765,4 +828,15 @@ private function shareObjectToArray(IShare $share) { 'password' => $share->getPassword() ]; } + + /** + * @return User + */ + private function getUser() { + if (self::$user == null){ + $app = new Application(); + self::$user = $app->getContainer()->query('UserSession')->getUser(); + } + return self::$user; + } }