Completed
Push — master ( a89f9a...3036b1 )
by Morris
29:19 queued 12:13
created

isRemoteGroupSharingAllowed()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 3
nop 1
dl 9
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * @copyright Copyright (c) 2016, ownCloud, Inc.
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Björn Schießle <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Maxence Lange <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
namespace OCA\Files_Sharing\Controller;
31
32
use OCP\AppFramework\Http\DataResponse;
33
use OCP\AppFramework\OCS\OCSBadRequestException;
34
use OCP\AppFramework\OCSController;
35
use OCP\Collaboration\Collaborators\ISearch;
36
use OCP\IRequest;
37
use OCP\IConfig;
38
use OCP\IURLGenerator;
39
use OCP\Share;
40
use OCP\Share\IManager;
41
42
class ShareesAPIController extends OCSController {
43
	/** @var IConfig */
44
	protected $config;
45
46
	/** @var IURLGenerator */
47
	protected $urlGenerator;
48
49
	/** @var IManager */
50
	protected $shareManager;
51
52
	/** @var bool */
53
	protected $shareWithGroupOnly = false;
54
55
	/** @var bool */
56
	protected $shareeEnumeration = true;
57
58
	/** @var int */
59
	protected $offset = 0;
60
61
	/** @var int */
62
	protected $limit = 10;
63
64
	/** @var array */
65
	protected $result = [
66
		'exact' => [
67
			'users' => [],
68
			'groups' => [],
69
			'remotes' => [],
70
			'remote_groups' => [],
71
			'emails' => [],
72
			'circles' => [],
73
		],
74
		'users' => [],
75
		'groups' => [],
76
		'remotes' => [],
77
		'remote_groups' => [],
78
		'emails' => [],
79
		'lookup' => [],
80
		'circles' => [],
81
	];
82
83
	protected $reachedEndFor = [];
84
	/** @var ISearch */
85
	private $collaboratorSearch;
86
87
	/**
88
	 * @param string $appName
89
	 * @param IRequest $request
90
	 * @param IConfig $config
91
	 * @param IURLGenerator $urlGenerator
92
	 * @param IManager $shareManager
93
	 * @param ISearch $collaboratorSearch
94
	 */
95 View Code Duplication
	public function __construct(
96
		string $appName,
97
		IRequest $request,
98
		IConfig $config,
99
		IURLGenerator $urlGenerator,
100
		IManager $shareManager,
101
		ISearch $collaboratorSearch
102
	) {
103
		parent::__construct($appName, $request);
104
105
		$this->config = $config;
106
		$this->urlGenerator = $urlGenerator;
107
		$this->shareManager = $shareManager;
108
		$this->collaboratorSearch = $collaboratorSearch;
109
	}
110
111
	/**
112
	 * @NoAdminRequired
113
	 *
114
	 * @param string $search
115
	 * @param string $itemType
116
	 * @param int $page
117
	 * @param int $perPage
118
	 * @param int|int[] $shareType
119
	 * @param bool $lookup
120
	 * @return DataResponse
121
	 * @throws OCSBadRequestException
122
	 */
123
	public function search(string $search = '', string $itemType = null, int $page = 1, int $perPage = 200, $shareType = null, bool $lookup = true): DataResponse {
124
125
		// only search for string larger than a given threshold
126
		$threshold = (int)$this->config->getSystemValue('sharing.minSearchStringLength', 0);
127
		if (strlen($search) < $threshold) {
128
			return new DataResponse($this->result);
129
		}
130
131
		// never return more than the max. number of results configured in the config.php
132
		$maxResults = (int)$this->config->getSystemValue('sharing.maxAutocompleteResults', 0);
133
		if ($maxResults > 0) {
134
			$perPage = min($perPage, $maxResults);
135
		}
136
		if ($perPage <= 0) {
137
			throw new OCSBadRequestException('Invalid perPage argument');
138
		}
139
		if ($page <= 0) {
140
			throw new OCSBadRequestException('Invalid page');
141
		}
142
143
		$shareTypes = [
144
			Share::SHARE_TYPE_USER,
145
		];
146
147
		if ($itemType === null) {
148
			throw new OCSBadRequestException('Missing itemType');
149
		} elseif ($itemType === 'file' || $itemType === 'folder') {
150
			if ($this->shareManager->allowGroupSharing()) {
151
				$shareTypes[] = Share::SHARE_TYPE_GROUP;
152
			}
153
154
			if ($this->isRemoteSharingAllowed($itemType)) {
155
				$shareTypes[] = Share::SHARE_TYPE_REMOTE;
156
			}
157
158
			if ($this->isRemoteGroupSharingAllowed($itemType)) {
159
				$shareTypes[] = Share::SHARE_TYPE_REMOTE_GROUP;
160
			}
161
162
			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
163
				$shareTypes[] = Share::SHARE_TYPE_EMAIL;
164
			}
165
		} else {
166
			$shareTypes[] = Share::SHARE_TYPE_GROUP;
167
			$shareTypes[] = Share::SHARE_TYPE_EMAIL;
168
		}
169
170
		// FIXME: DI
171
		if (\OC::$server->getAppManager()->isEnabledForUser('circles') && class_exists('\OCA\Circles\ShareByCircleProvider')) {
172
			$shareTypes[] = Share::SHARE_TYPE_CIRCLE;
173
		}
174
175
		if (isset($_GET['shareType']) && is_array($_GET['shareType'])) {
176
			$shareTypes = array_intersect($shareTypes, $_GET['shareType']);
177
			sort($shareTypes);
178
		} else if (is_numeric($shareType)) {
179
			$shareTypes = array_intersect($shareTypes, [(int) $shareType]);
180
			sort($shareTypes);
181
		}
182
183
		$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
184
		$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
185
		$this->limit = (int) $perPage;
186
		$this->offset = $perPage * ($page - 1);
187
188
		list($result, $hasMoreResults) = $this->collaboratorSearch->search($search, $shareTypes, $lookup, $this->limit, $this->offset);
189
190
		// extra treatment for 'exact' subarray, with a single merge expected keys might be lost
191
		if(isset($result['exact'])) {
192
			$result['exact'] = array_merge($this->result['exact'], $result['exact']);
193
		}
194
		$this->result = array_merge($this->result, $result);
195
		$response = new DataResponse($this->result);
196
197
		if ($hasMoreResults) {
198
			$response->addHeader('Link', $this->getPaginationLink($page, [
199
				'search' => $search,
200
				'itemType' => $itemType,
201
				'shareType' => $shareTypes,
202
				'perPage' => $perPage,
203
			]));
204
		}
205
206
		return $response;
207
	}
208
209
	/**
210
	 * Method to get out the static call for better testing
211
	 *
212
	 * @param string $itemType
213
	 * @return bool
214
	 */
215 View Code Duplication
	protected function isRemoteSharingAllowed(string $itemType): bool {
216
		try {
217
			// FIXME: static foo makes unit testing unnecessarily difficult
218
			$backend = \OC\Share\Share::getBackend($itemType);
219
			return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE);
220
		} catch (\Exception $e) {
221
			return false;
222
		}
223
	}
224
225 View Code Duplication
	protected function isRemoteGroupSharingAllowed(string $itemType): bool {
226
		try {
227
			// FIXME: static foo makes unit testing unnecessarily difficult
228
			$backend = \OC\Share\Share::getBackend($itemType);
229
			return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE_GROUP);
230
		} catch (\Exception $e) {
231
			return false;
232
		}
233
	}
234
235
236
	/**
237
	 * Generates a bunch of pagination links for the current page
238
	 *
239
	 * @param int $page Current page
240
	 * @param array $params Parameters for the URL
241
	 * @return string
242
	 */
243
	protected function getPaginationLink(int $page, array $params): string {
244
		if ($this->isV2()) {
245
			$url = $this->urlGenerator->getAbsoluteURL('/ocs/v2.php/apps/files_sharing/api/v1/sharees') . '?';
246
		} else {
247
			$url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?';
248
		}
249
		$params['page'] = $page + 1;
250
		return '<' . $url . http_build_query($params) . '>; rel="next"';
251
	}
252
253
	/**
254
	 * @return bool
255
	 */
256
	protected function isV2(): bool {
257
		return $this->request->getScriptName() === '/ocs/v2.php';
258
	}
259
}
260