Notifier.php 9.9 KB

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