Completed
Pull Request — master (#362)
by Maxence
01:51
created

FileShare::feedBroadcaster()   A

Complexity

Conditions 5
Paths 10

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.2728
c 0
b 0
f 0
cc 5
nc 10
nop 3
1
<?php declare(strict_types=1);
2
3
4
/**
5
 * Circles - Bring cloud-users closer together.
6
 *
7
 * This file is licensed under the Affero General Public License version 3 or
8
 * later. See the COPYING file.
9
 *
10
 * @author Maxence Lange <[email protected]>
11
 * @copyright 2017
12
 * @license GNU AGPL version 3 or any later version
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
 *
27
 */
28
29
30
namespace OCA\Circles\GlobalScale;
31
32
33
use daita\MySmallPhpTools\Model\SimpleDataStore;
34
use Exception;
35
use OC\Share20\Share;
36
use OCA\Circles\Exceptions\BroadcasterIsNotCompatibleException;
37
use OCA\Circles\Exceptions\CircleDoesNotExistException;
38
use OCA\Circles\Exceptions\GSStatusException;
39
use OCA\Circles\Exceptions\TokenDoesNotExistException;
40
use OCA\Circles\IBroadcaster;
41
use OCA\Circles\Model\Circle;
42
use OCA\Circles\Model\GlobalScale\GSEvent;
43
use OCA\Circles\Model\GlobalScale\GSShare;
44
use OCA\Circles\Model\Member;
45
use OCA\Circles\Model\SharingFrame;
46
use OCA\Circles\Service\ConfigService;
47
use OCA\Circles\Service\MiscService;
48
use OCP\AppFramework\QueryException;
49
use OCP\Files\NotFoundException;
50
use OCP\Share\Exceptions\IllegalIDChangeException;
51
use OCP\Share\Exceptions\ShareNotFound;
52
use OCP\Share\IShare;
53
54
55
/**
56
 * Class FileShare
57
 *
58
 * @package OCA\Circles\GlobalScale
59
 */
60
class FileShare extends AGlobalScaleEvent {
61
62
63
	/**
64
	 * @param GSEvent $event
65
	 * @param bool $localCheck
66
	 * @param bool $mustBeChecked
67
	 *
68
	 * @throws GSStatusException
69
	 * @throws TokenDoesNotExistException
70
	 */
71
	public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChecked = false): void {
72
		// TODO: might be a bad idea, all process of the sharing should be managed from here.
73
		// Even if we are not in a GS setup.
74
		// The reason is that if a mail needs to be send, all mail address associated to the circle needs to be retrieved
75
		if (!$this->configService->getGSStatus(ConfigService::GS_ENABLED)) {
76
			return;
77
		}
78
		\OC::$server->getLogger()->log(3, '### 0');
79
		// if event/file is local, we generate a federate share for the same circle on other instances
80
		if ($event->getSource() === $this->configService->getLocalCloudId()) {
81
			$circle = $event->getCircle();
0 ignored issues
show
Unused Code introduced by
$circle is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
82
83
			\OC::$server->getLogger()->log(3, '### 1');
84
85
			try {
86
				$share = $this->getShareFromData($event->getData());
87
			} catch (Exception $e) {
88
				return;
89
			}
90
91
			\OC::$server->getLogger()->log(3, '### 2');
92
93
94
			$this->miscService->log('### ' . json_encode($event->getData()));
95
96
			try {
97
				$node = $share->getNode();
98
				$filename = $node->getName();
99
			} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
100
				$filename = '/testTest.md';
101
			}
102
103
			$event->getData()
104
				  ->s('gs_federated', $share->getToken())
105
				  ->s('gs_filename', '/' . $filename);
106
		}
107
108
	}
109
110
111
	/**
112
	 * @param GSEvent $event
113
	 *
114
	 * @throws GSStatusException
115
	 */
116
	public function manage(GSEvent $event): void {
117
		// TODO: might be a bad idea, all process of the sharing should be managed from here.
118
		// Even if we are not in a GS setup.
119
		// The reason is that if a mail needs to be send, all mail address associated to the circle needs to be retrieved
120
		if (!$this->configService->getGSStatus(ConfigService::GS_ENABLED)) {
121
			return;
122
		}
123
124
		// if event is not local, we create a federated file to the right instance of Nextcloud, using the right token
125
		if ($event->getSource() !== $this->configService->getLocalCloudId()) {
126
			try {
127
				$share = $this->getShareFromData($event->getData());
128
			} catch (Exception $e) {
129
				return;
130
			}
131
132
			$data = $event->getData();
133
			$token = $data->g('gs_federated');
134
			$filename = $data->g('gs_filename');
135
136
			$gsShare = new GSShare($share->getSharedWith(), $token);
137
			$gsShare->setOwner($share->getShareOwner());
138
			$gsShare->setInstance($event->getSource());
139
			$gsShare->setParent(-1);
140
			$gsShare->setMountPoint($filename);
141
142
			$this->gsSharesRequest->create($gsShare);
143
		}
144
145
	}
146
147
148
	/**
149
	 * @param GSEvent[] $events
150
	 */
151
	public function result(array $events): void {
152
	}
153
154
155
	/**
156
	 * @param GSEvent $event
157
	 *
158
	 * @throws BroadcasterIsNotCompatibleException
159
	 * @throws GSStatusException
160
	 */
161
	private function generateFederatedShare(GSEvent $event) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
162
		$data = $event->getData();
163
		$frame = SharingFrame::fromJSON(json_encode($data->gAll()));
164
165
		try {
166
			$broadcaster = \OC::$server->query((string)$frame->getHeader('broadcast'));
167
			if (!($broadcaster instanceof IBroadcaster)) {
168
				throw new BroadcasterIsNotCompatibleException();
169
			}
170
171
			$frameCircle = $frame->getCircle();
172
			$circle = $this->circlesRequest->forceGetCircle($frameCircle->getUniqueId());
173
		} catch (QueryException | CircleDoesNotExistException $e) {
174
			return;
175
		}
176
177
		$this->feedBroadcaster($broadcaster, $frame, $circle);
0 ignored issues
show
Bug introduced by
It seems like $frame defined by \OCA\Circles\Model\Shari..._encode($data->gAll())) on line 163 can be null; however, OCA\Circles\GlobalScale\...hare::feedBroadcaster() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
178
	}
179
180
181
	/**
182
	 * @param IBroadcaster $broadcaster
183
	 * @param SharingFrame $frame
184
	 * @param Circle $circle
185
	 */
186
	private function feedBroadcaster(IBroadcaster $broadcaster, SharingFrame $frame, Circle $circle) {
187
		$broadcaster->init();
188
189
		if ($circle->getType() !== Circle::CIRCLES_PERSONAL) {
190
			$broadcaster->createShareToCircle($frame, $circle);
191
		}
192
193
		$members =
194
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MEMBER, true);
195
		foreach ($members AS $member) {
196
			$this->parseMember($member);
197
198
			if ($member->isBroadcasting()) {
199
				$broadcaster->createShareToMember($frame, $member);
200
			}
201
202
			if ($member->getInstance() !== '') {
203
				$this->miscService->log('#### GENERATE FEDERATED CIRCLES SHARE ' . $member->getInstance());
204
			}
205
		}
206
	}
207
208
209
	/**
210
	 * @param Member $member
211
	 */
212
	private function parseMember(Member &$member) {
213
		$this->parseMemberFromContact($member);
214
	}
215
216
217
	/**
218
	 * on Type Contact, we convert the type to MAIL and retrieve the first mail of the list.
219
	 * If no email, we set the member as not broadcasting.
220
	 *
221
	 * @param Member $member
222
	 */
223
	private function parseMemberFromContact(Member &$member) {
224
		if ($member->getType() !== Member::TYPE_CONTACT) {
225
			return;
226
		}
227
228
		$contact = MiscService::getContactData($member->getUserId());
229
		if (!key_exists('EMAIL', $contact)) {
230
			$member->broadcasting(false);
231
232
			return;
233
		}
234
235
		$member->setType(Member::TYPE_MAIL);
236
		$member->setUserId(array_shift($contact['EMAIL']));
237
	}
238
239
240
	/**
241
	 * @param SimpleDataStore $data
242
	 *
243
	 * @return IShare
244
	 * @throws ShareNotFound
245
	 * @throws IllegalIDChangeException
246
	 */
247
	private function getShareFromData(SimpleDataStore $data) {
248
		$frame = SharingFrame::fromArray($data->gArray('frame'));
249
		$payload = $frame->getPayload();
250
		if (!key_exists('share', $payload)) {
251
			throw new ShareNotFound();
252
		}
253
254
		return $this->generateShare($payload['share']);
255
	}
256
257
258
	/**
259
	 * recreate the share from the JSON payload.
260
	 *
261
	 * @param array $data
262
	 *
263
	 * @return IShare
264
	 * @throws IllegalIDChangeException
265
	 */
266
	private function generateShare($data): IShare {
267
		$share = new Share($this->rootFolder, $this->userManager);
268
		$share->setId($data['id']);
269
		$share->setSharedBy($data['sharedBy']);
270
		$share->setSharedWith($data['sharedWith']);
271
		$share->setNodeId($data['nodeId']);
272
		$share->setShareOwner($data['shareOwner']);
273
		$share->setPermissions($data['permissions']);
274
		$share->setToken($data['token']);
275
		$share->setPassword($data['password']);
276
277
		return $share;
278
	}
279
280
281
}
282