Passed
Push — master ( 465e91...f452e2 )
by Roeland
12:18 queued 10s
created

PrincipalProxyTrait::isReadProxyPrincipal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 1
1
<?php
2
/**
3
 * @copyright 2019, Georg Ehrke <[email protected]>
4
 *
5
 * @author Georg Ehrke <[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
namespace OCA\DAV\Traits;
24
25
use OCA\DAV\CalDAV\Proxy\Proxy;
26
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
27
use Sabre\DAV\Exception;
28
29
/**
30
 * Trait PrincipalTrait
31
 *
32
 * @package OCA\DAV\Traits
33
 */
34
trait PrincipalProxyTrait {
35
36
	/**
37
	 * Returns the list of members for a group-principal
38
	 *
39
	 * @param string $principal
40
	 * @return string[]
41
	 * @throws Exception
42
	 */
43
	public function getGroupMemberSet($principal) {
44
		$members = [];
45
46
		if ($this->isProxyPrincipal($principal)) {
47
			$realPrincipal = $this->getPrincipalUriFromProxyPrincipal($principal);
48
			$principalArray = $this->getPrincipalByPath($realPrincipal);
0 ignored issues
show
Bug introduced by
It seems like getPrincipalByPath() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

48
			/** @scrutinizer ignore-call */ 
49
   $principalArray = $this->getPrincipalByPath($realPrincipal);
Loading history...
49
			if (!$principalArray) {
50
				throw new Exception('Principal not found');
51
			}
52
53
			$proxies = $this->proxyMapper->getProxiesOf($principalArray['uri']);
54
			foreach ($proxies as $proxy) {
55
				if ($this->isReadProxyPrincipal($principal) && $proxy->getPermissions() === ProxyMapper::PERMISSION_READ) {
56
					$members[] = $proxy->getProxyId();
57
				}
58
59
				if ($this->isWriteProxyPrincipal($principal) && $proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) {
60
					$members[] = $proxy->getProxyId();
61
				}
62
			}
63
		}
64
65
		return $members;
66
	}
67
68
	/**
69
	 * Returns the list of groups a principal is a member of
70
	 *
71
	 * @param string $principal
72
	 * @param bool $needGroups
73
	 * @return array
74
	 * @throws Exception
75
	 */
76
	public function getGroupMembership($principal, $needGroups = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $needGroups is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

76
	public function getGroupMembership($principal, /** @scrutinizer ignore-unused */ $needGroups = false) {

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

Loading history...
77
		list($prefix, $name) = \Sabre\Uri\split($principal);
78
79
		if ($prefix !== $this->principalPrefix) {
80
			return [];
81
		}
82
83
		$principalArray = $this->getPrincipalByPath($principal);
84
		if (!$principalArray) {
85
			throw new Exception('Principal not found');
86
		}
87
88
		$groups = [];
89
		$proxies = $this->proxyMapper->getProxiesFor($principal);
90
		foreach ($proxies as $proxy) {
91
			if ($proxy->getPermissions() === ProxyMapper::PERMISSION_READ) {
92
				$groups[] = $proxy->getOwnerId() . '/calendar-proxy-read';
93
			}
94
95
			if ($proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) {
96
				$groups[] = $proxy->getOwnerId() . '/calendar-proxy-write';
97
			}
98
		}
99
100
		return $groups;
101
	}
102
103
	/**
104
	 * Updates the list of group members for a group principal.
105
	 *
106
	 * The principals should be passed as a list of uri's.
107
	 *
108
	 * @param string $principal
109
	 * @param string[] $members
110
	 * @throws Exception
111
	 */
112
	public function setGroupMemberSet($principal, array $members) {
113
		list($principalUri, $target) = \Sabre\Uri\split($principal);
114
115
		if ($target !== 'calendar-proxy-write' && $target !== 'calendar-proxy-read') {
116
			throw new Exception('Setting members of the group is not supported yet');
117
		}
118
119
		$masterPrincipalArray = $this->getPrincipalByPath($principalUri);
120
		if (!$masterPrincipalArray) {
121
			throw new Exception('Principal not found');
122
		}
123
124
		$permission = ProxyMapper::PERMISSION_READ;
125
		if ($target === 'calendar-proxy-write') {
126
			$permission |= ProxyMapper::PERMISSION_WRITE;
127
		}
128
129
		list($prefix, $owner) = \Sabre\Uri\split($principalUri);
0 ignored issues
show
Comprehensibility Best Practice introduced by
This list assign is not used and could be removed.
Loading history...
130
		$proxies = $this->proxyMapper->getProxiesOf($principalUri);
131
132
		foreach ($members as $member) {
133
			list($prefix, $name) = \Sabre\Uri\split($member);
134
135
			if ($prefix !== $this->principalPrefix) {
136
				throw new Exception('Invalid member group prefix: ' . $prefix);
137
			}
138
139
			$principalArray = $this->getPrincipalByPath($member);
140
			if (!$principalArray) {
141
				throw new Exception('Principal not found');
142
			}
143
144
			$found = false;
145
			foreach ($proxies as $proxy) {
146
				if ($proxy->getProxyId() === $member) {
147
					$found = true;
148
					$proxy->setPermissions($proxy->getPermissions() | $permission);
149
					$this->proxyMapper->update($proxy);
150
151
					$proxies = array_filter($proxies, function(Proxy $p) use ($proxy) {
152
						return $p->getId() !== $proxy->getId();
153
					});
154
					break;
155
				}
156
			}
157
158
			if ($found === false) {
159
				$proxy = new Proxy();
160
				$proxy->setOwnerId($principalUri);
161
				$proxy->setProxyId($member);
162
				$proxy->setPermissions($permission);
163
				$this->proxyMapper->insert($proxy);
164
			}
165
		}
166
167
		// Delete all remaining proxies
168
		foreach ($proxies as $proxy) {
169
			// Write and Read Proxies have individual requests,
170
			// so only delete proxies of this permission
171
			if ($proxy->getPermissions() === $permission) {
172
				$this->proxyMapper->delete($proxy);
173
			}
174
		}
175
	}
176
177
	/**
178
	 * @param string $principalUri
179
	 * @return bool
180
	 */
181
	private function isProxyPrincipal(string $principalUri):bool {
182
		list($realPrincipalUri, $proxy) = \Sabre\Uri\split($principalUri);
183
		list($prefix, $userId) = \Sabre\Uri\split($realPrincipalUri);
184
185
		if (!isset($prefix) || !isset($userId)) {
186
			return false;
187
		}
188
		if ($prefix !== $this->principalPrefix) {
189
			return false;
190
		}
191
192
		return $proxy === 'calendar-proxy-read'
193
			|| $proxy === 'calendar-proxy-write';
194
195
	}
196
197
	/**
198
	 * @param string $principalUri
199
	 * @return bool
200
	 */
201
	private function isReadProxyPrincipal(string $principalUri):bool {
202
		list(, $proxy) = \Sabre\Uri\split($principalUri);
203
		return $proxy === 'calendar-proxy-read';
204
	}
205
206
	/**
207
	 * @param string $principalUri
208
	 * @return bool
209
	 */
210
	private function isWriteProxyPrincipal(string $principalUri):bool {
211
		list(, $proxy) = \Sabre\Uri\split($principalUri);
212
		return $proxy === 'calendar-proxy-write';
213
	}
214
215
	/**
216
	 * @param string $principalUri
217
	 * @return string
218
	 */
219
	private function getPrincipalUriFromProxyPrincipal(string $principalUri):string {
220
		list($realPrincipalUri, ) = \Sabre\Uri\split($principalUri);
221
		return $realPrincipalUri;
222
	}
223
}
224