Completed
Push — master ( 5a6198...a64e14 )
by Maxence
17s queued 10s
created

SharesController::checkContactMail()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2017
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\Circles\Controller;
28
29
use daita\MySmallPhpTools\Traits\TStringTools;
30
use Exception;
31
use OCA\Circles\Db\SharesRequest;
32
use OCA\Circles\Db\TokensRequest;
33
use OCA\Circles\Exceptions\MemberDoesNotExistException;
34
use OCA\Circles\Model\Member;
35
use OCA\Circles\Model\SharesToken;
36
use OCA\Circles\Model\SharingFrame;
37
use OCA\Circles\Service\BroadcastService;
38
use OCA\Circles\Service\ConfigService;
39
use OCA\Circles\Service\MembersService;
40
use OCA\Circles\Service\MiscService;
41
use OCA\Circles\Service\SharingFrameService;
42
use OCP\AppFramework\Controller;
43
use OCP\AppFramework\Http\DataResponse;
44
use OCP\AppFramework\Http\RedirectResponse;
45
use OCP\IRequest;
46
use OCP\IURLGenerator;
47
48
49
/**
50
 * Class SharesController
51
 *
52
 * @package OCA\Circles\Controller
53
 */
54
class SharesController extends Controller {
55
56
57
	use TStringTools;
58
59
60
	/** @var TokensRequest */
61
	private $tokenRequest;
62
63
	/** @var SharesRequest */
64
	private $sharesRequest;
65
66
	/** @var IURLGenerator */
67
	private $urlGenerator;
68
69
	/** @var MembersService */
70
	private $membersService;
71
72
	/** @var BroadcastService */
73
	private $broadcastService;
74
75
	/** @var SharingFrameService */
76
	private $sharingFrameService;
77
78
	/** @var ConfigService */
79
	private $configService;
80
81
	/** @var MiscService */
82
	private $miscService;
83
84
85
	/**
86
	 * SharesController constructor.
87
	 *
88
	 * @param $appName
89
	 * @param IRequest $request
90
	 * @param TokensRequest $tokenRequest
91
	 * @param SharesRequest $sharesRequest
92
	 * @param IURLGenerator $urlGenerator
93
	 * @param MembersService $membersService
94
	 * @param BroadcastService $broadcastService
95
	 * @param SharingFrameService $sharingFrameService
96
	 * @param ConfigService $configService
97
	 * @param MiscService $miscService
98
	 */
99 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...
100
		$appName, IRequest $request, TokensRequest $tokenRequest, SharesRequest $sharesRequest,
101
		IUrlGenerator $urlGenerator, MembersService $membersService,
102
		BroadcastService $broadcastService,
103
		SharingFrameService $sharingFrameService, ConfigService $configService,
104
		MiscService $miscService
105
	) {
106
		parent::__construct($appName, $request);
107
108
		$this->tokenRequest = $tokenRequest;
109
		$this->sharesRequest = $sharesRequest;
110
		$this->urlGenerator = $urlGenerator;
111
		$this->membersService = $membersService;
112
		$this->broadcastService = $broadcastService;
113
		$this->sharingFrameService = $sharingFrameService;
114
		$this->configService = $configService;
115
		$this->miscService = $miscService;
116
	}
117
118
119
	/**
120
	 * Called by the JavaScript API when creating a new Share item that will be
121
	 * broadcasted to the circle itself, and any other circle linked to it.
122
	 *
123
	 * @NoAdminRequired
124
	 * @NoSubAdminRequired
125
	 *
126
	 * @param string $circleUniqueId
127
	 * @param string $source
128
	 * @param string $type
129
	 * @param array $payload
130
	 *
131
	 * @return DataResponse
132
	 */
133
	public function create($circleUniqueId, $source, $type, $payload) {
134
135
		try {
136
			$share = new SharingFrame($source, $type);
137
			$share->setPayload($payload);
138
139
			$this->sharingFrameService->createFrame($circleUniqueId, $share);
140
		} catch (\Exception $e) {
141
			return $this->fail(
142
				[
143
					'circle_id' => $circleUniqueId,
144
					'source'    => $source,
145
					'type'      => $type,
146
					'payload'   => $payload,
147
					'error'     => $e->getMessage()
148
				]
149
			);
150
		}
151
152
		return $this->success(
153
			[
154
				'circle_id' => $circleUniqueId,
155
				'source'    => $source,
156
				'type'      => $type,
157
				'payload'   => $payload
158
			]
159
		);
160
	}
161
162
163
	/**
164
	 * initShareDelivery()
165
	 *
166
	 * Note: this function will close the request mid-run from the client but will still
167
	 * running its process.
168
	 *
169
	 * Called by locally, the function will get the SharingFrame by its uniqueId from the database.
170
	 * After closing the socket, will broadcast the Frame locally and - if Federated Shares are
171
	 * enable - will deliver it to each remote circles linked to the circle the Payload belongs to.
172
	 *
173
	 * A status response is sent to free the client process before starting to broadcast the item
174
	 * to other federated links.
175
	 *
176
	 * @PublicPage
177
	 * @NoCSRFRequired
178
	 *
179
	 * @param string $circleId
180
	 * @param string $frameId
181
	 *
182
	 * @return DataResponse
183
	 */
184
	public function initShareDelivery($circleId, $frameId) {
185
186
		try {
187
			$frame = $this->sharingFrameService->getFrameFromUniqueId($circleId, $frameId);
188
		} catch (Exception $e) {
189
			return $this->fail($e->getMessage());
190
		}
191
192
		// We don't want to keep the connection up
193
		$this->miscService->asyncAndLeaveClientOutOfThis('done');
194
195
		$this->broadcastService->broadcastFrame($frame);
0 ignored issues
show
Bug introduced by
It seems like $frame defined by $this->sharingFrameServi...Id($circleId, $frameId) on line 187 can be null; however, OCA\Circles\Service\Broa...rvice::broadcastFrame() 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...
196
197
		// TODO - do not update cloudId to avoid duplicate, use it's own field and keep cloudId
198
		$this->sharingFrameService->updateFrameWithCloudId($frame);
0 ignored issues
show
Bug introduced by
It seems like $frame defined by $this->sharingFrameServi...Id($circleId, $frameId) on line 187 can be null; however, OCA\Circles\Service\Shar...pdateFrameWithCloudId() 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...
199
		if ($this->configService->isFederatedCirclesAllowed()) {
200
			$this->sharingFrameService->forwardSharingFrame($frame);
0 ignored issues
show
Bug introduced by
It seems like $frame defined by $this->sharingFrameServi...Id($circleId, $frameId) on line 187 can be null; however, OCA\Circles\Service\Shar...::forwardSharingFrame() 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...
201
		}
202
203
		exit();
204
	}
205
206
207
	/**
208
	 * @PublicPage
209
	 * @NoCSRFRequired
210
	 *
211
	 * @param string $token
212
	 *
213
	 * @return RedirectResponse
214
	 */
215
	public function public(string $token) {
216
		try {
217
			$shareToken = $this->tokenRequest->getByToken($token);
218
			$this->checkContactMail($shareToken);
219
220
			$token = $this->sharesRequest->getTokenByShareId($shareToken->getShareId());
221
		} catch (Exception $e) {
222
			$this->miscService->log(
223
				'token ' . $token . ' not found - ' . get_class($e) . ' - ' . $e->getMessage()
224
			);
225
			$token = $this->uuid(15);
226
		}
227
228
		return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/s/' . $token));
229
	}
230
231
232
	/**
233
	 * @param SharesToken $shareToken
234
	 *
235
	 * @throws MemberDoesNotExistException
236
	 */
237
	private function checkContactMail(SharesToken $shareToken) {
238
		try {
239
			$this->membersService->getMember(
240
				$shareToken->getCircleId(), $shareToken->getUserId(), Member::TYPE_MAIL, true
241
			);
242
243
			return;
244
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
245
		}
246
247
		try {
248
			$this->membersService->getMember(
249
				$shareToken->getCircleId(), $shareToken->getUserId(), Member::TYPE_MAIL, true
250
			);
251
252
			return;
253
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
254
		}
255
256
		throw new MemberDoesNotExistException();
257
	}
258
}
259
260