Notifier.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
  5. *
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Roeland Jago Douma <roeland@famdouma.nl>
  8. * @author Sascha Wiswedel <sascha.wiswedel@nextcloud.com>
  9. *
  10. * @license GNU AGPL version 3 or any later version
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License as
  14. * published by the Free Software Foundation, either version 3 of the
  15. * License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. *
  25. */
  26. namespace OCA\Files\Notification;
  27. use OCA\Files\BackgroundJob\TransferOwnership;
  28. use OCA\Files\Db\TransferOwnershipMapper;
  29. use OCP\AppFramework\Db\DoesNotExistException;
  30. use OCP\AppFramework\Utility\ITimeFactory;
  31. use OCP\BackgroundJob\IJobList;
  32. use OCP\IURLGenerator;
  33. use OCP\IUser;
  34. use OCP\IUserManager;
  35. use OCP\L10N\IFactory;
  36. use OCP\Notification\IAction;
  37. use OCP\Notification\IDismissableNotifier;
  38. use OCP\Notification\IManager;
  39. use OCP\Notification\INotification;
  40. use OCP\Notification\INotifier;
  41. class Notifier implements INotifier, IDismissableNotifier {
  42. /** @var IFactory */
  43. protected $l10nFactory;
  44. /** @var IURLGenerator */
  45. protected $urlGenerator;
  46. /** @var TransferOwnershipMapper */
  47. private $mapper;
  48. /** @var IManager */
  49. private $notificationManager;
  50. /** @var IUserManager */
  51. private $userManager;
  52. /** @var ITimeFactory */
  53. private $timeFactory;
  54. /** @var IJobList */
  55. private $jobList;
  56. public function __construct(IFactory $l10nFactory,
  57. IURLGenerator $urlGenerator,
  58. TransferOwnershipMapper $mapper,
  59. IManager $notificationManager,
  60. IUserManager $userManager,
  61. IJobList $jobList,
  62. ITimeFactory $timeFactory) {
  63. $this->l10nFactory = $l10nFactory;
  64. $this->urlGenerator = $urlGenerator;
  65. $this->jobList = $jobList;
  66. $this->mapper = $mapper;
  67. $this->notificationManager = $notificationManager;
  68. $this->userManager = $userManager;
  69. $this->timeFactory = $timeFactory;
  70. }
  71. public function getID(): string {
  72. return 'files';
  73. }
  74. public function getName(): string {
  75. return $this->l10nFactory->get('files')->t('Files');
  76. }
  77. /**
  78. * @param INotification $notification
  79. * @param string $languageCode The code of the language that should be used to prepare the notification
  80. * @return INotification
  81. * @throws \InvalidArgumentException When the notification was not prepared by a notifier
  82. */
  83. public function prepare(INotification $notification, string $languageCode): INotification {
  84. if ($notification->getApp() !== 'files') {
  85. throw new \InvalidArgumentException('Unhandled app');
  86. }
  87. $imagePath = $this->urlGenerator->imagePath('files', 'folder-move.svg');
  88. $iconUrl = $this->urlGenerator->getAbsoluteURL($imagePath);
  89. $notification->setIcon($iconUrl);
  90. return match($notification->getSubject()) {
  91. 'transferownershipRequest' => $this->handleTransferownershipRequest($notification, $languageCode),
  92. 'transferownershipRequestDenied' => $this->handleTransferOwnershipRequestDenied($notification, $languageCode),
  93. 'transferOwnershipFailedSource' => $this->handleTransferOwnershipFailedSource($notification, $languageCode),
  94. 'transferOwnershipFailedTarget' => $this->handleTransferOwnershipFailedTarget($notification, $languageCode),
  95. 'transferOwnershipDoneSource' => $this->handleTransferOwnershipDoneSource($notification, $languageCode),
  96. 'transferOwnershipDoneTarget' => $this->handleTransferOwnershipDoneTarget($notification, $languageCode),
  97. default => throw new \InvalidArgumentException('Unhandled subject')
  98. };
  99. }
  100. public function handleTransferownershipRequest(INotification $notification, string $languageCode): INotification {
  101. $l = $this->l10nFactory->get('files', $languageCode);
  102. $id = $notification->getObjectId();
  103. $param = $notification->getSubjectParameters();
  104. $approveAction = $notification->createAction()
  105. ->setParsedLabel($l->t('Accept'))
  106. ->setPrimary(true)
  107. ->setLink(
  108. $this->urlGenerator->getAbsoluteURL(
  109. $this->urlGenerator->linkTo(
  110. '',
  111. 'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
  112. )
  113. ),
  114. IAction::TYPE_POST
  115. );
  116. $disapproveAction = $notification->createAction()
  117. ->setParsedLabel($l->t('Reject'))
  118. ->setPrimary(false)
  119. ->setLink(
  120. $this->urlGenerator->getAbsoluteURL(
  121. $this->urlGenerator->linkTo(
  122. '',
  123. 'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
  124. )
  125. ),
  126. IAction::TYPE_DELETE
  127. );
  128. $sourceUser = $this->getUser($param['sourceUser']);
  129. $notification->addParsedAction($approveAction)
  130. ->addParsedAction($disapproveAction)
  131. ->setRichSubject(
  132. $l->t('Incoming ownership transfer from {user}'),
  133. [
  134. 'user' => [
  135. 'type' => 'user',
  136. 'id' => $sourceUser->getUID(),
  137. 'name' => $sourceUser->getDisplayName(),
  138. ],
  139. ])
  140. ->setRichMessage(
  141. $l->t("Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour."),
  142. [
  143. 'path' => [
  144. 'type' => 'highlight',
  145. 'id' => $param['targetUser'] . '::' . $param['nodeName'],
  146. 'name' => $param['nodeName'],
  147. ]
  148. ]);
  149. return $notification;
  150. }
  151. public function handleTransferOwnershipRequestDenied(INotification $notification, string $languageCode): INotification {
  152. $l = $this->l10nFactory->get('files', $languageCode);
  153. $param = $notification->getSubjectParameters();
  154. $targetUser = $this->getUser($param['targetUser']);
  155. $notification->setRichSubject($l->t('Ownership transfer denied'))
  156. ->setRichMessage(
  157. $l->t('Your ownership transfer of {path} was denied by {user}.'),
  158. [
  159. 'path' => [
  160. 'type' => 'highlight',
  161. 'id' => $param['targetUser'] . '::' . $param['nodeName'],
  162. 'name' => $param['nodeName'],
  163. ],
  164. 'user' => [
  165. 'type' => 'user',
  166. 'id' => $targetUser->getUID(),
  167. 'name' => $targetUser->getDisplayName(),
  168. ],
  169. ]);
  170. return $notification;
  171. }
  172. public function handleTransferOwnershipFailedSource(INotification $notification, string $languageCode): INotification {
  173. $l = $this->l10nFactory->get('files', $languageCode);
  174. $param = $notification->getSubjectParameters();
  175. $targetUser = $this->getUser($param['targetUser']);
  176. $notification->setRichSubject($l->t('Ownership transfer failed'))
  177. ->setRichMessage(
  178. $l->t('Your ownership transfer of {path} to {user} failed.'),
  179. [
  180. 'path' => [
  181. 'type' => 'highlight',
  182. 'id' => $param['targetUser'] . '::' . $param['nodeName'],
  183. 'name' => $param['nodeName'],
  184. ],
  185. 'user' => [
  186. 'type' => 'user',
  187. 'id' => $targetUser->getUID(),
  188. 'name' => $targetUser->getDisplayName(),
  189. ],
  190. ]);
  191. return $notification;
  192. }
  193. public function handleTransferOwnershipFailedTarget(INotification $notification, string $languageCode): INotification {
  194. $l = $this->l10nFactory->get('files', $languageCode);
  195. $param = $notification->getSubjectParameters();
  196. $sourceUser = $this->getUser($param['sourceUser']);
  197. $notification->setRichSubject($l->t('Ownership transfer failed'))
  198. ->setRichMessage(
  199. $l->t('The ownership transfer of {path} from {user} failed.'),
  200. [
  201. 'path' => [
  202. 'type' => 'highlight',
  203. 'id' => $param['sourceUser'] . '::' . $param['nodeName'],
  204. 'name' => $param['nodeName'],
  205. ],
  206. 'user' => [
  207. 'type' => 'user',
  208. 'id' => $sourceUser->getUID(),
  209. 'name' => $sourceUser->getDisplayName(),
  210. ],
  211. ]);
  212. return $notification;
  213. }
  214. public function handleTransferOwnershipDoneSource(INotification $notification, string $languageCode): INotification {
  215. $l = $this->l10nFactory->get('files', $languageCode);
  216. $param = $notification->getSubjectParameters();
  217. $targetUser = $this->getUser($param['targetUser']);
  218. $notification->setRichSubject($l->t('Ownership transfer done'))
  219. ->setRichMessage(
  220. $l->t('Your ownership transfer of {path} to {user} has completed.'),
  221. [
  222. 'path' => [
  223. 'type' => 'highlight',
  224. 'id' => $param['targetUser'] . '::' . $param['nodeName'],
  225. 'name' => $param['nodeName'],
  226. ],
  227. 'user' => [
  228. 'type' => 'user',
  229. 'id' => $targetUser->getUID(),
  230. 'name' => $targetUser->getDisplayName(),
  231. ],
  232. ]);
  233. return $notification;
  234. }
  235. public function handleTransferOwnershipDoneTarget(INotification $notification, string $languageCode): INotification {
  236. $l = $this->l10nFactory->get('files', $languageCode);
  237. $param = $notification->getSubjectParameters();
  238. $sourceUser = $this->getUser($param['sourceUser']);
  239. $notification->setRichSubject($l->t('Ownership transfer done'))
  240. ->setRichMessage(
  241. $l->t('The ownership transfer of {path} from {user} has completed.'),
  242. [
  243. 'path' => [
  244. 'type' => 'highlight',
  245. 'id' => $param['sourceUser'] . '::' . $param['nodeName'],
  246. 'name' => $param['nodeName'],
  247. ],
  248. 'user' => [
  249. 'type' => 'user',
  250. 'id' => $sourceUser->getUID(),
  251. 'name' => $sourceUser->getDisplayName(),
  252. ],
  253. ]);
  254. return $notification;
  255. }
  256. public function dismissNotification(INotification $notification): void {
  257. if ($notification->getApp() !== 'files') {
  258. throw new \InvalidArgumentException('Unhandled app');
  259. }
  260. if ($notification->getSubject() !== 'transferownershipRequest') {
  261. throw new \InvalidArgumentException('Unhandled notification type');
  262. }
  263. // TODO: This should all be moved to a service that also the transferownershipController uses.
  264. try {
  265. $transferOwnership = $this->mapper->getById((int)$notification->getObjectId());
  266. } catch (DoesNotExistException $e) {
  267. return;
  268. }
  269. if ($this->jobList->has(TransferOwnership::class, [
  270. 'id' => $transferOwnership->getId(),
  271. ])) {
  272. return;
  273. }
  274. $notification = $this->notificationManager->createNotification();
  275. $notification->setUser($transferOwnership->getSourceUser())
  276. ->setApp('files')
  277. ->setDateTime($this->timeFactory->getDateTime())
  278. ->setSubject('transferownershipRequestDenied', [
  279. 'sourceUser' => $transferOwnership->getSourceUser(),
  280. 'targetUser' => $transferOwnership->getTargetUser(),
  281. 'nodeName' => $transferOwnership->getNodeName()
  282. ])
  283. ->setObject('transfer', (string)$transferOwnership->getId());
  284. $this->notificationManager->notify($notification);
  285. $this->mapper->delete($transferOwnership);
  286. }
  287. protected function getUser(string $userId): IUser {
  288. $user = $this->userManager->get($userId);
  289. if ($user instanceof IUser) {
  290. return $user;
  291. }
  292. throw new \InvalidArgumentException('User not found');
  293. }
  294. }