These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @author Joas Schilling <[email protected]> |
||
4 | * @author Juan Pablo Villafáñez <[email protected]> |
||
5 | * @author Robin Appelman <[email protected]> |
||
6 | * @author Robin McCorkell <[email protected]> |
||
7 | * |
||
8 | * @copyright Copyright (c) 2016, ownCloud GmbH. |
||
9 | * @license AGPL-3.0 |
||
10 | * |
||
11 | * This code is free software: you can redistribute it and/or modify |
||
12 | * it under the terms of the GNU Affero General Public License, version 3, |
||
13 | * as published by the Free Software Foundation. |
||
14 | * |
||
15 | * This program is distributed in the hope that it will be useful, |
||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 | * GNU Affero General Public License for more details. |
||
19 | * |
||
20 | * You should have received a copy of the GNU Affero General Public License, version 3, |
||
21 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
||
22 | * |
||
23 | */ |
||
24 | |||
25 | namespace OCA\Files_External\Controller; |
||
26 | |||
27 | use OCA\Files_External\Lib\Auth\AuthMechanism; |
||
28 | use OCA\Files_External\Lib\Auth\IUserProvided; |
||
29 | use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; |
||
30 | use OCP\ILogger; |
||
31 | use \OCP\IRequest; |
||
32 | use \OCP\IL10N; |
||
33 | use \OCP\AppFramework\Http\DataResponse; |
||
34 | use \OCP\AppFramework\Http; |
||
35 | use OCA\Files_External\Service\UserGlobalStoragesService; |
||
36 | use OCA\Files_External\NotFoundException; |
||
37 | use OCA\Files_External\Lib\StorageConfig; |
||
38 | use \OCA\Files_External\Lib\Backend\Backend; |
||
39 | use OCP\IUserSession; |
||
40 | |||
41 | /** |
||
42 | * User global storages controller |
||
43 | */ |
||
44 | class UserGlobalStoragesController extends StoragesController { |
||
45 | /** |
||
46 | * @var IUserSession |
||
47 | */ |
||
48 | private $userSession; |
||
49 | |||
50 | /** |
||
51 | * Creates a new user global storages controller. |
||
52 | * |
||
53 | * @param string $AppName application name |
||
54 | * @param IRequest $request request object |
||
55 | * @param IL10N $l10n l10n service |
||
56 | * @param UserGlobalStoragesService $userGlobalStoragesService storage service |
||
57 | * @param IUserSession $userSession |
||
58 | */ |
||
59 | View Code Duplication | public function __construct( |
|
60 | $AppName, |
||
61 | IRequest $request, |
||
62 | IL10N $l10n, |
||
63 | UserGlobalStoragesService $userGlobalStoragesService, |
||
64 | IUserSession $userSession, |
||
65 | ILogger $logger |
||
66 | ) { |
||
67 | parent::__construct( |
||
68 | $AppName, |
||
69 | $request, |
||
70 | $l10n, |
||
71 | $userGlobalStoragesService, |
||
72 | $logger |
||
73 | ); |
||
74 | $this->userSession = $userSession; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Get all storage entries |
||
79 | * |
||
80 | * @return DataResponse |
||
81 | * |
||
82 | * @NoAdminRequired |
||
83 | */ |
||
84 | public function index() { |
||
85 | $storages = $this->service->getUniqueStorages(); |
||
0 ignored issues
–
show
|
|||
86 | |||
87 | // remove configuration data, this must be kept private |
||
88 | foreach ($storages as $storage) { |
||
89 | $this->sanitizeStorage($storage); |
||
90 | } |
||
91 | |||
92 | return new DataResponse( |
||
93 | $storages, |
||
94 | Http::STATUS_OK |
||
95 | ); |
||
96 | } |
||
97 | |||
98 | View Code Duplication | protected function manipulateStorageConfig(StorageConfig $storage) { |
|
99 | /** @var AuthMechanism */ |
||
100 | $authMechanism = $storage->getAuthMechanism(); |
||
101 | $authMechanism->manipulateStorageConfig($storage, $this->userSession->getUser()); |
||
102 | /** @var Backend */ |
||
103 | $backend = $storage->getBackend(); |
||
104 | $backend->manipulateStorageConfig($storage, $this->userSession->getUser()); |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * Get an external storage entry. |
||
109 | * |
||
110 | * @param int $id storage id |
||
111 | * @param bool $testOnly whether to storage should only test the connection or do more things |
||
112 | * @return DataResponse |
||
113 | * |
||
114 | * @NoAdminRequired |
||
115 | */ |
||
116 | View Code Duplication | public function show($id, $testOnly = true) { |
|
117 | try { |
||
118 | $storage = $this->service->getStorage($id); |
||
119 | |||
120 | $this->updateStorageStatus($storage, $testOnly); |
||
0 ignored issues
–
show
It seems like
$storage defined by $this->service->getStorage($id) on line 118 can be null ; however, OCA\Files_External\Contr...::updateStorageStatus() 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);
}
}
![]() |
|||
121 | } catch (NotFoundException $e) { |
||
122 | return new DataResponse( |
||
123 | [ |
||
124 | 'message' => (string)$this->l10n->t('Storage with id "%i" not found', [$id]) |
||
125 | ], |
||
126 | Http::STATUS_NOT_FOUND |
||
127 | ); |
||
128 | } |
||
129 | |||
130 | $this->sanitizeStorage($storage); |
||
131 | |||
132 | return new DataResponse( |
||
133 | $storage, |
||
134 | Http::STATUS_OK |
||
135 | ); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Update an external storage entry. |
||
140 | * Only allows setting user provided backend fields |
||
141 | * |
||
142 | * @param int $id storage id |
||
143 | * @param array $backendOptions backend-specific options |
||
144 | * @param bool $testOnly whether to storage should only test the connection or do more things |
||
145 | * |
||
146 | * @return DataResponse |
||
147 | * |
||
148 | * @NoAdminRequired |
||
149 | */ |
||
150 | public function update( |
||
151 | $id, |
||
152 | $backendOptions, |
||
153 | $testOnly = true |
||
154 | ) { |
||
155 | try { |
||
156 | $storage = $this->service->getStorage($id); |
||
157 | $authMechanism = $storage->getAuthMechanism(); |
||
158 | if ($authMechanism instanceof IUserProvided) { |
||
159 | $authMechanism->saveBackendOptions($this->userSession->getUser(), $id, $backendOptions); |
||
0 ignored issues
–
show
It seems like
$this->userSession->getUser() can be null ; however, saveBackendOptions() 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);
}
}
![]() |
|||
160 | $authMechanism->manipulateStorageConfig($storage, $this->userSession->getUser()); |
||
161 | } else { |
||
162 | return new DataResponse( |
||
163 | [ |
||
164 | 'message' => (string)$this->l10n->t('Storage with id "%i" is not user editable', [$id]) |
||
165 | ], |
||
166 | Http::STATUS_FORBIDDEN |
||
167 | ); |
||
168 | } |
||
169 | } catch (NotFoundException $e) { |
||
170 | return new DataResponse( |
||
171 | [ |
||
172 | 'message' => (string)$this->l10n->t('Storage with id "%i" not found', [$id]) |
||
173 | ], |
||
174 | Http::STATUS_NOT_FOUND |
||
175 | ); |
||
176 | } |
||
177 | |||
178 | $this->updateStorageStatus($storage, $testOnly); |
||
0 ignored issues
–
show
It seems like
$storage defined by $this->service->getStorage($id) on line 156 can be null ; however, OCA\Files_External\Contr...::updateStorageStatus() 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);
}
}
![]() |
|||
179 | $this->sanitizeStorage($storage); |
||
180 | |||
181 | return new DataResponse( |
||
182 | $storage, |
||
183 | Http::STATUS_OK |
||
184 | ); |
||
185 | |||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Remove sensitive data from a StorageConfig before returning it to the user |
||
190 | * |
||
191 | * @param StorageConfig $storage |
||
192 | */ |
||
193 | protected function sanitizeStorage(StorageConfig $storage) { |
||
194 | $storage->setBackendOptions([]); |
||
195 | $storage->setMountOptions([]); |
||
196 | |||
197 | if ($storage->getAuthMechanism() instanceof IUserProvided) { |
||
198 | try { |
||
199 | $storage->getAuthMechanism()->manipulateStorageConfig($storage, $this->userSession->getUser()); |
||
200 | } catch (InsufficientDataForMeaningfulAnswerException $e) { |
||
201 | // not configured yet |
||
202 | } |
||
203 | } |
||
204 | } |
||
205 | |||
206 | } |
||
207 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: