1<?php
2
3declare(strict_types=1);
4
5/**
6 * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
7 *
8 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
9 * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
10 * @author Joas Schilling <coding@schilljs.com>
11 * @author John Molakvoæ <skjnldsv@protonmail.com>
12 * @author Julius Härtl <jus@bitgrid.net>
13 * @author Roeland Jago Douma <roeland@famdouma.nl>
14 *
15 * @license GNU AGPL version 3 or any later version
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU Affero General Public License as
19 * published by the Free Software Foundation, either version 3 of the
20 * License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 */
31namespace OCA\Files_Sharing\Controller;
32
33use OCP\App\IAppManager;
34use OCP\AppFramework\Http\DataResponse;
35use OCP\AppFramework\OCS\OCSException;
36use OCP\AppFramework\OCS\OCSNotFoundException;
37use OCP\AppFramework\OCSController;
38use OCP\AppFramework\QueryException;
39use OCP\Files\IRootFolder;
40use OCP\Files\NotFoundException;
41use OCP\IGroupManager;
42use OCP\IRequest;
43use OCP\IServerContainer;
44use OCP\IUserManager;
45use OCP\Share\Exceptions\GenericShareException;
46use OCP\Share\Exceptions\ShareNotFound;
47use OCP\Share\IManager as ShareManager;
48use OCP\Share\IShare;
49
50class DeletedShareAPIController extends OCSController {
51
52	/** @var ShareManager */
53	private $shareManager;
54
55	/** @var string */
56	private $userId;
57
58	/** @var IUserManager */
59	private $userManager;
60
61	/** @var IGroupManager */
62	private $groupManager;
63
64	/** @var IRootFolder */
65	private $rootFolder;
66
67	/** @var IAppManager */
68	private $appManager;
69
70	/** @var IServerContainer */
71	private $serverContainer;
72
73	public function __construct(string $appName,
74								IRequest $request,
75								ShareManager $shareManager,
76								string $UserId,
77								IUserManager $userManager,
78								IGroupManager $groupManager,
79								IRootFolder $rootFolder,
80								IAppManager $appManager,
81								IServerContainer $serverContainer) {
82		parent::__construct($appName, $request);
83
84		$this->shareManager = $shareManager;
85		$this->userId = $UserId;
86		$this->userManager = $userManager;
87		$this->groupManager = $groupManager;
88		$this->rootFolder = $rootFolder;
89		$this->appManager = $appManager;
90		$this->serverContainer = $serverContainer;
91	}
92
93	/**
94	 * @suppress PhanUndeclaredClassMethod
95	 */
96	private function formatShare(IShare $share): array {
97		$result = [
98			'id' => $share->getFullId(),
99			'share_type' => $share->getShareType(),
100			'uid_owner' => $share->getSharedBy(),
101			'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
102			'permissions' => 0,
103			'stime' => $share->getShareTime()->getTimestamp(),
104			'parent' => null,
105			'expiration' => null,
106			'token' => null,
107			'uid_file_owner' => $share->getShareOwner(),
108			'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
109			'path' => $share->getTarget(),
110		];
111		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
112		$nodes = $userFolder->getById($share->getNodeId());
113		if (empty($nodes)) {
114			// fallback to guessing the path
115			$node = $userFolder->get($share->getTarget());
116			if ($node === null || $share->getTarget() === '') {
117				throw new NotFoundException();
118			}
119		} else {
120			$node = $nodes[0];
121		}
122
123		$result['path'] = $userFolder->getRelativePath($node->getPath());
124		if ($node instanceof \OCP\Files\Folder) {
125			$result['item_type'] = 'folder';
126		} else {
127			$result['item_type'] = 'file';
128		}
129		$result['mimetype'] = $node->getMimetype();
130		$result['storage_id'] = $node->getStorage()->getId();
131		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
132		$result['item_source'] = $node->getId();
133		$result['file_source'] = $node->getId();
134		$result['file_parent'] = $node->getParent()->getId();
135		$result['file_target'] = $share->getTarget();
136
137		$expiration = $share->getExpirationDate();
138		if ($expiration !== null) {
139			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
140		}
141
142		if ($share->getShareType() === IShare::TYPE_GROUP) {
143			$group = $this->groupManager->get($share->getSharedWith());
144			$result['share_with'] = $share->getSharedWith();
145			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
146		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
147			$result['share_with'] = $share->getSharedWith();
148			$result['share_with_displayname'] = '';
149
150			try {
151				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
152			} catch (QueryException $e) {
153			}
154		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
155			$result['share_with'] = $share->getSharedWith();
156			$result['share_with_displayname'] = '';
157
158			try {
159				$result = array_merge($result, $this->getDeckShareHelper()->formatShare($share));
160			} catch (QueryException $e) {
161			}
162		}
163
164		return $result;
165	}
166
167	/**
168	 * @NoAdminRequired
169	 */
170	public function index(): DataResponse {
171		$groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
172		$roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
173		$deckShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_DECK, null, -1, 0);
174
175		$shares = array_merge($groupShares, $roomShares, $deckShares);
176
177		$shares = array_map(function (IShare $share) {
178			return $this->formatShare($share);
179		}, $shares);
180
181		return new DataResponse($shares);
182	}
183
184	/**
185	 * @NoAdminRequired
186	 *
187	 * @throws OCSException
188	 */
189	public function undelete(string $id): DataResponse {
190		try {
191			$share = $this->shareManager->getShareById($id, $this->userId);
192		} catch (ShareNotFound $e) {
193			throw new OCSNotFoundException('Share not found');
194		}
195
196		if ($share->getPermissions() !== 0) {
197			throw new OCSNotFoundException('No deleted share found');
198		}
199
200		try {
201			$this->shareManager->restoreShare($share, $this->userId);
202		} catch (GenericShareException $e) {
203			throw new OCSException('Something went wrong');
204		}
205
206		return new DataResponse([]);
207	}
208
209	/**
210	 * Returns the helper of DeletedShareAPIController for room shares.
211	 *
212	 * If the Talk application is not enabled or the helper is not available
213	 * a QueryException is thrown instead.
214	 *
215	 * @return \OCA\Talk\Share\Helper\DeletedShareAPIController
216	 * @throws QueryException
217	 */
218	private function getRoomShareHelper() {
219		if (!$this->appManager->isEnabledForUser('spreed')) {
220			throw new QueryException();
221		}
222
223		return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
224	}
225
226	/**
227	 * Returns the helper of ShareAPIHelper for deck shares.
228	 *
229	 * If the Deck application is not enabled or the helper is not available
230	 * a QueryException is thrown instead.
231	 *
232	 * @return \OCA\Deck\Sharing\ShareAPIHelper
233	 * @throws QueryException
234	 */
235	private function getDeckShareHelper() {
236		if (!$this->appManager->isEnabledForUser('deck')) {
237			throw new QueryException();
238		}
239
240		return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
241	}
242}
243