Completed
Push — master ( 92b059...082de6 )
by Maxence
28s queued 11s
created

ExternalFilesService::getMountPoints()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
rs 9.6666
cc 2
nc 2
nop 1
1
<?php
2
declare(strict_types=1);
3
4
5
/**
6
 * Files_FullTextSearch - Index the content of your files
7
 *
8
 * This file is licensed under the Affero General Public License version 3 or
9
 * later. See the COPYING file.
10
 *
11
 * @author Maxence Lange <[email protected]>
12
 * @copyright 2018
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
30
31
namespace OCA\Files_FullTextSearch\Service;
32
33
34
use daita\MySmallPhpTools\Traits\TArrayTools;
35
use Exception;
36
use OC;
37
use OC\App\AppManager;
38
use OCA\Files_External\Lib\StorageConfig;
39
use OCA\Files_External\Service\GlobalStoragesService;
40
use OCA\Files_External\Service\UserGlobalStoragesService;
41
use OCA\Files_FullTextSearch\Exceptions\ExternalMountNotFoundException;
42
use OCA\Files_FullTextSearch\Exceptions\ExternalMountWithNoViewerException;
43
use OCA\Files_FullTextSearch\Exceptions\FileIsNotIndexableException;
44
use OCA\Files_FullTextSearch\Exceptions\KnownFileSourceException;
45
use OCA\Files_FullTextSearch\Model\FilesDocument;
46
use OCA\Files_FullTextSearch\Model\MountPoint;
47
use OCP\App\IAppManager;
48
use OCP\Files\IRootFolder;
49
use OCP\Files\Node;
50
use OCP\FullTextSearch\Model\IIndex;
51
use OCP\IGroupManager;
52
use OCP\IUserManager;
53
use OCP\Share\IManager;
54
55
56
/**
57
 * Class ExternalFilesService
58
 *
59
 * @package OCA\Files_FullTextSearch\Service
60
 */
61
class ExternalFilesService {
62
63
64
	use TArrayTools;
65
66
67
	/** @var IRootFolder */
68
	private $rootFolder;
69
70
	/** @var AppManager */
71
	private $appManager;
72
73
	/** @var IUserManager */
74
	private $userManager;
75
76
	/** @var IManager */
77
	private $shareManager;
78
79
	/** @var UserGlobalStoragesService */
80
	private $userGlobalStoragesService;
81
82
	/** @var GlobalStoragesService */
83
	private $globalStoragesService;
84
85
	/** @var IGroupManager */
86
	private $groupManager;
87
88
	/** @var LocalFilesService */
89
	private $localFilesService;
90
91
	/** @var ConfigService */
92
	private $configService;
93
94
	/** @var MiscService */
95
	private $miscService;
96
97
98
	/**
99
	 * ExternalFilesService constructor.
100
	 *
101
	 * @param IRootFolder $rootFolder
102
	 * @param IAppManager $appManager
103
	 * @param IUserManager $userManager
104
	 * @param IGroupManager $groupManager
105
	 * @param IManager $shareManager
106
	 * @param LocalFilesService $localFilesService
107
	 * @param ConfigService $configService
108
	 * @param MiscService $miscService
109
	 */
110 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
111
		IRootFolder $rootFolder, IAppManager $appManager, IUserManager $userManager,
112
		IGroupManager $groupManager, IManager $shareManager, LocalFilesService $localFilesService,
113
		ConfigService $configService, MiscService $miscService
114
	) {
115
		$this->rootFolder = $rootFolder;
116
		$this->appManager = $appManager;
0 ignored issues
show
Documentation Bug introduced by
It seems like $appManager of type object<OCP\App\IAppManager> is incompatible with the declared type object<OC\App\AppManager> of property $appManager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
117
		$this->userManager = $userManager;
118
		$this->groupManager = $groupManager;
119
		$this->shareManager = $shareManager;
120
121
		$this->localFilesService = $localFilesService;
122
123
		$this->configService = $configService;
124
		$this->miscService = $miscService;
125
	}
126
127
128
	/**
129
	 * @param string $userId
130
	 */
131
	public function initExternalFilesForUser(string $userId) {
0 ignored issues
show
Unused Code introduced by
The parameter $userId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
132
		if (!$this->appManager->isInstalled('files_external')) {
133
			return;
134
		}
135
136
		$this->userGlobalStoragesService = OC::$server->getUserGlobalStoragesService();
137
		$this->globalStoragesService = OC::$server->getGlobalStoragesService();
138
	}
139
140
141
	/**
142
	 * @param Node $file
143
	 *
144
	 * @param string $source
145
	 *
146
	 * @throws FileIsNotIndexableException
147
	 * @throws KnownFileSourceException
148
	 */
149 View Code Duplication
	public function getFileSource(Node $file, string &$source) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150
		if ($this->globalStoragesService === null
151
			|| $file->getMountPoint()
152
					->getMountType() !== 'external') {
153
			return;
154
		}
155
156
		$this->getMountPoint($file);
157
		$source = ConfigService::FILES_EXTERNAL;
158
159
		throw new KnownFileSourceException();
160
	}
161
162
163
	/**
164
	 * @param FilesDocument $document
165
	 * @param array $users
166
	 */
167
	public function getShareUsers(FilesDocument $document, array &$users) {
168
		if ($document->getSource() !== ConfigService::FILES_EXTERNAL) {
169
			return;
170
		}
171
172
		$this->localFilesService->getSharedUsersFromAccess($document->getAccess(), $users);
173
	}
174
175
176
	/**
177
	 * @param FilesDocument $document
178
	 * @param Node $file
179
	 *
180
	 * @throws FileIsNotIndexableException
181
	 */
182
	public function updateDocumentAccess(FilesDocument &$document, Node $file) {
183
		if ($document->getSource() !== ConfigService::FILES_EXTERNAL) {
184
			return;
185
		}
186
187
		$mount = $this->getMountPoint($file);
188
		$access = $document->getAccess();
189
190
		if ($this->isMountFullGlobal($mount)) {
191
			$access->addUsers(['__all']);
192
		} else {
193
			$access->addUsers($mount->getUsers());
194
			$access->addGroups($mount->getGroups());
195
//		 	$access->addCircles($mount->getCircles());
196
		}
197
198
		// twist 'n tweak.
199
		if (!$mount->isGlobal()) {
200
			$access->setOwnerId($mount->getUsers()[0]);
201
		}
202
203
		$document->getIndex()
204
				 ->addOptionInt('external_mount_id', $mount->getId());
205
		$document->setAccess($access);
206
207
		$document->setAccess($access);
208
	}
209
210
211
	/**
212
	 * @param MountPoint $mount
213
	 *
214
	 * @return bool
215
	 */
216
	private function isMountFullGlobal(MountPoint $mount): bool {
217
		if (sizeof($mount->getGroups()) > 0) {
218
			return false;
219
		}
220
221
		if (sizeof($mount->getUsers()) !== 1) {
222
			return false;
223
		}
224
225
		if ($mount->getUsers()[0] === 'all') {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $mount->getUsers()[0] === 'all';.
Loading history...
226
			return true;
227
		}
228
229
		return false;
230
	}
231
232
233
	/**
234
	 * @param Node $file
235
	 *
236
	 * @return MountPoint
237
	 * @throws FileIsNotIndexableException
238
	 */
239
	private function getMountPoint(Node $file): MountPoint {
240
241
		try {
242
			return $this->getExternalMountById(
243
				$file->getMountPoint()
244
					 ->getMountId()
245
			);
246
		} catch (ExternalMountNotFoundException $e) {
247
			throw new FileIsNotIndexableException('issue while getMountPoint');
248
		}
249
	}
250
251
252
	/**
253
	 * @param int $externalMountId
254
	 *
255
	 * @return MountPoint
256
	 * @throws ExternalMountNotFoundException
257
	 */
258
	private function getExternalMountById(int $externalMountId): MountPoint {
259
		if ($this->globalStoragesService === null
260
			|| $externalMountId === 0) {
261
			throw new ExternalMountNotFoundException();
262
		}
263
264
		try {
265
			$mount = $this->globalStoragesService->getStorage($externalMountId);
266
			$mountPoint = new MountPoint();
267
			$mountPoint->setId($mount->getId())
268
					   ->setPath($mount->getMountPoint())
269
					   ->setGroups($mount->getApplicableGroups())
270
					   ->setUsers($mount->getApplicableUsers())
271
					   ->setGlobal(($mount->getType() === StorageConfig::MOUNT_TYPE_ADMIN));
272
		} catch (Exception $e) {
273
			throw new ExternalMountNotFoundException();
274
		}
275
276
		return $mountPoint;
277
	}
278
279
280
	/**
281
	 * @param IIndex $index
282
	 */
283
	public function impersonateOwner(IIndex $index) {
284
		if ($index->getSource() !== ConfigService::FILES_EXTERNAL) {
285
			return;
286
		}
287
288
		$groupFolderId = $index->getOptionInt('external_mount_id', 0);
289
		try {
290
			$mount = $this->getExternalMountById($groupFolderId);
291
		} catch (ExternalMountNotFoundException $e) {
292
			return;
293
		}
294
295
		try {
296
			$index->setOwnerId($this->getRandomUserFromMountPoint($mount));
297
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
298
		}
299
	}
300
301
302
	/**
303
	 * @param MountPoint $mount
304
	 *
305
	 * @return string
306
	 * @throws ExternalMountWithNoViewerException
307
	 */
308
	private function getRandomUserFromMountPoint(MountPoint $mount): string {
309
310
		$users = $mount->getUsers();
311
		if (sizeof($users) > 0) {
312
			return $users[0];
313
		}
314
315
		$groups = $mount->getGroups();
316
		if (sizeof($groups) === 0) {
317
			$groups = ['admin'];
318
		}
319
320 View Code Duplication
		foreach ($groups as $groupName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
			$group = $this->groupManager->get($groupName);
322
			$users = $group->getUsers();
323
			if (sizeof($users) > 0) {
324
				return array_keys($users)[0];
325
			}
326
		}
327
328
		throw new ExternalMountWithNoViewerException(
329
			'cannot get a valid user for external mount'
330
		);
331
332
	}
333
334
}
335
336