Passed
Pull Request — master (#1234)
by René
03:57
created

ShareService::add()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 13
Bugs 3 Features 0
Metric Value
eloc 11
dl 0
loc 18
ccs 0
cts 16
cp 0
rs 9.6111
c 13
b 3
f 0
cc 5
nc 6
nop 3
crap 30
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
4
 *
5
 * @author René Gieling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Polls\Service;
25
26
use OCP\AppFramework\Db\DoesNotExistException;
27
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
28
use OCA\Polls\Exceptions\NotAuthorizedException;
29
use OCA\Polls\Exceptions\InvalidShareType;
30
use OCA\Polls\Exceptions\ShareAlreadyExistsException;
31
use OCA\Polls\Exceptions\NotFoundException;
32
33
use OCP\Security\ISecureRandom;
34
35
use OCA\Polls\Db\ShareMapper;
36
use OCA\Polls\Db\Share;
37
use OCA\Polls\Model\Acl;
38
use OCA\Polls\Model\UserGroupClass;
39
40
class ShareService {
41
42
	/** @var SystemService */
43
	private $systemService;
44
45
	/** @var ShareMapper */
46
	private $shareMapper;
47
48
	/** @var Share */
49
	private $share;
50
51
	/** @var MailService */
52
	private $mailService;
53
54
	/** @var Acl */
55
	private $acl;
56
57
	/**
58
	 * ShareController constructor.
59
	 * @param SystemService $systemService
60
	 * @param ShareMapper $shareMapper
61
	 * @param Share $share
62
	 * @param MailService $mailService
63
	 * @param Acl $acl
64
	 */
65
	public function __construct(
66
		SystemService $systemService,
67
		ShareMapper $shareMapper,
68
		Share $share,
69
		MailService $mailService,
70
		Acl $acl
71
	) {
72
		$this->systemService = $systemService;
73
		$this->shareMapper = $shareMapper;
74
		$this->share = $share;
75
		$this->mailService = $mailService;
76
		$this->acl = $acl;
77
	}
78
79
	/**
80
	 * Read all shares of a poll based on the poll id and return list as array
81
	 * @NoAdminRequired
82
	 * @param int $pollId
83
	 * @return array array of Share
84
	 * @throws NotAuthorizedException
85
	 * @throws NotFoundException
86
	 */
87
	public function list($pollId) {
88
		if (!$this->acl->set($pollId)->getAllowEdit()) {
89
			throw new NotAuthorizedException;
90
		}
91
92
		try {
93
			$shares = $this->shareMapper->findByPoll($pollId);
94
		} catch (DoesNotExistException $e) {
95
			return [];
96
		}
97
98
		return $shares;
99
	}
100
101
	/**
102
	 * Get share by token
103
	 * @NoAdminRequired
104
	 * @param string $token
105
	 * @return Share
106
	 * @throws NotFoundException
107
	 */
108
	public function get($token) {
109
		try {
110
			$this->share = $this->shareMapper->findByToken($token);
111
		} catch (DoesNotExistException $e) {
112
			throw new NotFoundException('Token ' . $token . ' does not exist');
113
		}
114
		// Allow users entering the poll with a public share access
115
116
		if ($this->share->getType() === Share::TYPE_PUBLIC && \OC::$server->getUserSession()->isLoggedIn()) {
117
			// Check if the user has already access
118
			if (!$this->acl->set($this->share->getPollId())->getAllowView()) {
119
120
				// Create a new share for this user, so he is allowed to access the poll later
121
				// via normal shared access and return the created share
122
				return $this->create(
123
					$this->share->getPollId(),
124
					UserGroupClass::getUserGroupChild(Share::TYPE_USER, \OC::$server->getUserSession()->getUser()->getUID()),
125
					true
126
				);
127
			}
128
		}
129
		return $this->share;
130
	}
131
132
	/**
133
	 * Get share by token
134
	 * @NoAdminRequired
135
	 * @param string $token
136
	 * @return Share
137
	 */
138
	public function setInvitationSent($token) {
139
		$share = $this->get($token);
140
		$share->setInvitationSent(time());
141
		return $this->shareMapper->update($share);
142
	}
143
144
	/**
145
	 * crate share
146
	 * @NoAdminRequired
147
	 * @param int $pollId
148
	 * @param UserGroupClass $userGroup
149
	 * @param bool $skipInvitation
150
	 * @return Share
151
	 */
152
	private function create($pollId, $userGroup, $skipInvitation = false) {
153
		$this->share = new Share();
154
		$this->share->setToken(\OC::$server->getSecureRandom()->generate(
155
			16,
156
			ISecureRandom::CHAR_DIGITS .
157
			ISecureRandom::CHAR_LOWER .
158
			ISecureRandom::CHAR_UPPER
159
		));
160
		$this->share->setPollId($pollId);
161
		$this->share->setInvitationSent($skipInvitation ? time() : 0);
162
		$this->share->setType($userGroup->getType());
163
		$this->share->setUserId($userGroup->getPublicId());
164
		$this->share->setDisplayName($userGroup->getDisplayName());
165
		$this->share->setEmailAddress($userGroup->getEmailAddress());
166
167
		return $this->shareMapper->insert($this->share);
168
	}
169
170
	/**
171
	 * Add share
172
	 * @NoAdminRequired
173
	 * @param int $pollId
174
	 * @param array $user
175
	 * @return Share
176
	 * @throws NotAuthorizedException
177
	 * @throws InvalidShareType
178
	 */
179
	public function add($pollId, $type, $userId = '') {
180
		if (!$this->acl->set($pollId)->getAllowEdit()) {
181
			throw new NotAuthorizedException;
182
		}
183
184
		if ($type !== UserGroupClass::TYPE_PUBLIC) {
185
			try {
186
				$this->shareMapper->findByPollAndUser($pollId, $userId);
187
				throw new ShareAlreadyExistsException;
188
			} catch (MultipleObjectsReturnedException $e) {
189
				throw new ShareAlreadyExistsException;
190
			} catch (DoesNotExistException $e) {
191
				// continue
192
			}
193
		}
194
195
		$userGroup = UserGroupClass::getUserGroupChild($type, $userId);
196
		return $this->create($pollId, $userGroup);
197
	}
198
199
	/**
200
	 * Set emailAddress to personal share
201
	 * or update an email share with the username
202
	 * @NoAdminRequired
203
	 * @param string $token
204
	 * @param string $emailAddress
205
	 * @return Share
206
	 * @throws InvalidShareType
207
	 * @throws NotFoundException
208
	 */
209
	public function setEmailAddress($token, $emailAddress) {
210
		try {
211
			$this->share = $this->shareMapper->findByToken($token);
212
		} catch (DoesNotExistException $e) {
213
			throw new NotFoundException('Token ' . $token . ' does not exist');
214
		}
215
216
		if ($this->share->getType() === Share::TYPE_EXTERNAL) {
217
			$this->systemService->validateEmailAddress($emailAddress);
218
			$this->share->setEmailAddress($emailAddress);
219
			// TODO: Send confirmation
220
			return $this->shareMapper->update($this->share);
221
		} else {
222
			throw new InvalidShareType('Email address can only be set in external shares.');
223
		}
224
	}
225
226
	/**
227
	 * Create a personal share from a public share
228
	 * or update an email share with the username
229
	 * @NoAdminRequired
230
	 * @param string $token
231
	 * @param string $userName
232
	 * @return Share
233
	 * @throws NotAuthorizedException
234
	 * @throws NotFoundException
235
	 */
236
	public function personal($token, $userName, $emailAddress = '') {
237
		try {
238
			$this->share = $this->shareMapper->findByToken($token);
239
		} catch (DoesNotExistException $e) {
240
			throw new NotFoundException('Token ' . $token . ' does not exist');
241
		}
242
243
		$this->systemService->validatePublicUsername($userName, $token);
244
		$this->systemService->validateEmailAddress($emailAddress, true);
245
246
		if ($this->share->getType() === Share::TYPE_PUBLIC) {
247
			// Create new external share for user, who entered the poll via public link
248
			$this->create(
249
				$this->share->getPollId(),
250
				UserGroupClass::getUserGroupChild(Share::TYPE_EXTERNAL, $userName, $userName, $emailAddress));
251
			if ($emailAddress) {
252
				$this->mailService->sendInvitation($this->share->getToken());
253
			}
254
255
			return $this->share;
256
		} elseif ($this->share->getType() === Share::TYPE_EMAIL
257
				|| $this->share->getType() === Share::TYPE_CONTACT) {
258
			// Convert Email and contact shares to external share, if user registeres
259
			$this->share->setType(Share::TYPE_EXTERNAL);
260
			$this->share->setUserId($userName);
261
			$this->share->setDisplayName($userName);
262
			$this->share->setEmailAddress($emailAddress);
263
			return $this->shareMapper->update($this->share);
264
		} else {
265
			throw new NotAuthorizedException;
266
		}
267
	}
268
269
	/**
270
	 * Delete share
271
	 * remove share
272
	 * @NoAdminRequired
273
	 * @param string $token
274
	 * @return Share
275
	 * @throws NotAuthorizedException
276
	 */
277
278
	public function delete($token) {
279
		try {
280
			$this->share = $this->shareMapper->findByToken($token);
281
			if (!$this->acl->set($this->share->getPollId())->getAllowEdit()) {
282
				throw new NotAuthorizedException;
283
			}
284
			$this->shareMapper->delete($this->share);
285
		} catch (DoesNotExistException $e) {
286
			// silently catch
287
		}
288
		return $token;
289
	}
290
}
291