PermissionService::userCan()   B
last analyzed

Complexity

Conditions 8
Paths 7

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 16
rs 7.7777
c 1
b 0
f 0
cc 8
eloc 9
nc 7
nop 2
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Julius Härtl <[email protected]>
4
 *
5
 * @author Julius Härtl <[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\Deck\Service;
25
26
use OCA\Deck\Db\Acl;
27
use OCA\Deck\Db\AclMapper;
28
use OCA\Deck\Db\BoardMapper;
29
use OCA\Deck\Db\IPermissionMapper;
30
use OCA\Deck\NoPermissionException;
31
use OCP\AppFramework\Db\DoesNotExistException;
32
use OCP\IGroupManager;
33
use OCP\ILogger;
34
35
36
37
class PermissionService {
38
39
	private $boardMapper;
40
	private $aclMapper;
41
	private $logger;
42
	private $userId;
43
44
	public function __construct(ILogger $logger, AclMapper $aclMapper, BoardMapper $boardMapper, IGroupManager $groupManager, $userId) {
45
		$this->aclMapper = $aclMapper;
46
		$this->boardMapper = $boardMapper;
47
		$this->logger = $logger;
48
		$this->groupManager = $groupManager;
0 ignored issues
show
Bug introduced by
The property groupManager does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
49
		$this->userId = $userId;
50
	}
51
52
	/**
53
	 * Get current user permissions for a board
54
	 *
55
	 * @param $boardId
56
	 * @return bool|array
57
	 */
58
	public function getPermissions($boardId) {
59
		$owner = $this->userIsBoardOwner($boardId);
60
		$acls = $this->aclMapper->findAll($boardId);
61
		return [
62
			Acl::PERMISSION_READ => $owner || $this->userCan($acls, Acl::PERMISSION_READ),
63
			Acl::PERMISSION_EDIT => $owner || $this->userCan($acls, Acl::PERMISSION_EDIT),
64
			Acl::PERMISSION_MANAGE => $owner || $this->userCan($acls, Acl::PERMISSION_MANAGE),
65
			Acl::PERMISSION_SHARE => $owner || $this->userCan($acls, Acl::PERMISSION_SHARE),
66
		];
67
	}
68
69
	/**
70
	 * check permissions for replacing dark magic middleware
71
	 *
72
	 * @param $mapper IPermissionMapper|null null if $id is a boardId
73
	 * @param $id int unique identifier of the Entity
74
	 * @param $permission int
75
	 * @return bool
76
	 * @throws NoPermissionException
77
	 */
78
	public function checkPermission($mapper, $id, $permission) {
79
		try {
80
			if ($mapper instanceof IPermissionMapper) {
81
				$boardId = $mapper->findBoardId($id);
82
			} else {
83
				$boardId = $id;
84
			}
85
			if ($boardId === null) {
86
				// Throw NoPermission to not leak information about existing entries
87
				throw new NoPermissionException('Permission denied');
88
			}
89
90
			if ($this->userIsBoardOwner($boardId)) {
91
				return true;
92
			}
93
			$acls = $this->aclMapper->findAll($boardId);
94
			$result = $this->userCan($acls, $permission);
95
			if ($result) {
96
				return true;
97
			}
98
99
		} catch (DoesNotExistException $exception) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\DoesNotExistException 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
			// Throw NoPermission to not leak information about existing entries
101
			throw new NoPermissionException('Permission denied');
102
		}
103
104
		throw new NoPermissionException('Permission denied.');
105
106
	}
107
108
	/**
109
	 * @param $boardId
110
	 * @return bool
111
	 */
112
	public function userIsBoardOwner($boardId) {
113
		$board = $this->boardMapper->find($boardId);
114
		if ($board && $this->userId === $board->getOwner()) {
115
			return true;
116
		}
117
		return false;
118
	}
119
120
	/**
121
	 * Check if permission matches the acl rules for current user and groups
122
	 *
123
	 * @param Acl[] $acls
124
	 * @param $permission
125
	 * @return bool
126
	 */
127
	public function userCan(array $acls, $permission) {
128
		// check for users
129
		foreach ($acls as $acl) {
130
			if ($acl->getType() === Acl::PERMISSION_TYPE_USER && $acl->getParticipant() === $this->userId) {
131
				return $acl->getPermission($permission);
132
			}
133
		}
134
		// check for groups
135
		$hasGroupPermission = false;
136
		foreach ($acls as $acl) {
137
			if (!$hasGroupPermission && $acl->getType() === Acl::PERMISSION_TYPE_GROUP && $this->groupManager->isInGroup($this->userId, $acl->getParticipant())) {
138
				$hasGroupPermission = $acl->getPermission($permission);
139
			}
140
		}
141
		return $hasGroupPermission;
142
	}
143
}