1 | <?php |
||||
2 | /** |
||||
3 | * BEdita, API-first content management framework |
||||
4 | * Copyright 2017 ChannelWeb Srl, Chialab Srl |
||||
5 | * |
||||
6 | * This file is part of BEdita: you can redistribute it and/or modify |
||||
7 | * it under the terms of the GNU Lesser General Public License as published |
||||
8 | * by the Free Software Foundation, either version 3 of the License, or |
||||
9 | * (at your option) any later version. |
||||
10 | * |
||||
11 | * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details. |
||||
12 | */ |
||||
13 | namespace BEdita\API\Controller; |
||||
14 | |||||
15 | use BEdita\Core\Utility\LoggedUser; |
||||
16 | use Cake\Core\Configure; |
||||
17 | use Cake\Http\ServerRequest; |
||||
18 | use Cake\ORM\TableRegistry; |
||||
19 | use Cake\Routing\Router; |
||||
20 | use Cake\Utility\Hash; |
||||
21 | use Cake\Utility\Inflector; |
||||
22 | use Zend\Diactoros\Uri; |
||||
23 | |||||
24 | /** |
||||
25 | * Controller for `/home` endpoint. |
||||
26 | * |
||||
27 | * @since 4.0.0 |
||||
28 | */ |
||||
29 | class HomeController extends AppController |
||||
30 | { |
||||
31 | |||||
32 | /** |
||||
33 | * Default endpoints with: |
||||
34 | * - supported methods, where 'ALL' means 'GET', 'POST', 'PATCH' and 'DELETE' are supported |
||||
35 | * - multiple types flag, if true multiple types are handled (like abstract object types or `/trash`) |
||||
36 | * |
||||
37 | * @var array |
||||
38 | */ |
||||
39 | protected $defaultEndpoints = [ |
||||
40 | '/auth' => [ |
||||
41 | 'methods' => ['GET', 'POST'], |
||||
42 | 'multiple_types' => false, |
||||
43 | ], |
||||
44 | '/admin' => [ |
||||
45 | 'methods' => 'ALL', |
||||
46 | 'multiple_types' => true, |
||||
47 | ], |
||||
48 | '/model' => [ |
||||
49 | 'methods' => 'ALL', |
||||
50 | 'multiple_types' => true, |
||||
51 | ], |
||||
52 | '/roles' => [ |
||||
53 | 'methods' => 'ALL', |
||||
54 | 'multiple_types' => false, |
||||
55 | ], |
||||
56 | '/signup' => [ |
||||
57 | 'methods' => ['POST'], |
||||
58 | 'multiple_types' => false, |
||||
59 | ], |
||||
60 | '/status' => [ |
||||
61 | 'methods' => ['GET'], |
||||
62 | 'multiple_types' => false, |
||||
63 | ], |
||||
64 | '/trash' => [ |
||||
65 | 'methods' => 'ALL', |
||||
66 | 'multiple_types' => true, |
||||
67 | ], |
||||
68 | ]; |
||||
69 | |||||
70 | /** |
||||
71 | * Default allowed methods for unlogged users |
||||
72 | * '/*' means: all other endpoints |
||||
73 | * |
||||
74 | * @var array |
||||
75 | */ |
||||
76 | protected $defaultAllowUnlogged = [ |
||||
77 | '/auth' => ['POST'], |
||||
78 | '/signup' => ['POST'], |
||||
79 | '/*' => ['GET'], |
||||
80 | ]; |
||||
81 | |||||
82 | /** |
||||
83 | * List API available endpoints |
||||
84 | * |
||||
85 | * @return void |
||||
86 | */ |
||||
87 | public function index() |
||||
88 | { |
||||
89 | $this->request->allowMethod(['get', 'head']); |
||||
0 ignored issues
–
show
|
|||||
90 | |||||
91 | $default = Hash::insert($this->defaultEndpoints, '{*}.object_type', false); |
||||
0 ignored issues
–
show
false of type false is incompatible with the type array|null expected by parameter $values of Cake\Utility\Hash::insert() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
92 | $endPoints = array_merge($this->objectTypesEndpoints(), $default); |
||||
93 | foreach ($endPoints as $e => $data) { |
||||
94 | $resources[$e] = $this->endpointFeatures($e, $data); |
||||
95 | } |
||||
96 | $project = Configure::read('Project'); |
||||
97 | $version = Configure::read('BEdita.version'); |
||||
98 | |||||
99 | $this->set('_meta', compact('resources', 'project', 'version')); |
||||
100 | $this->set('_serialize', []); |
||||
101 | } |
||||
102 | |||||
103 | /** |
||||
104 | * Return endpoint features to display in `/home` response |
||||
105 | * |
||||
106 | * @param string $endpoint Endpoint name |
||||
107 | * @param array $options Endpoint options - methods and multiple types flag |
||||
108 | * @return array Array of features |
||||
109 | */ |
||||
110 | protected function endpointFeatures($endpoint, $options) |
||||
111 | { |
||||
112 | $methods = $options['methods']; |
||||
113 | if ($methods === 'ALL') { |
||||
114 | $methods = ['GET', 'POST', 'PATCH', 'DELETE']; |
||||
115 | } |
||||
116 | $allow = []; |
||||
117 | foreach ($methods as $method) { |
||||
118 | if ($this->checkAuthorization($endpoint, $method)) { |
||||
119 | $allow[] = $method; |
||||
120 | } |
||||
121 | } |
||||
122 | |||||
123 | return [ |
||||
124 | 'href' => Router::url($endpoint, true), |
||||
125 | 'hints' => [ |
||||
126 | 'allow' => $allow, |
||||
127 | 'formats' => [ |
||||
128 | 'application/json', |
||||
129 | 'application/vnd.api+json', |
||||
130 | ], |
||||
131 | 'display' => [ |
||||
132 | 'label' => Inflector::camelize(substr($endpoint, 1)), |
||||
133 | ], |
||||
134 | 'object_type' => $options['object_type'], |
||||
135 | 'multiple_types' => $options['multiple_types'], |
||||
136 | ], |
||||
137 | ]; |
||||
138 | } |
||||
139 | |||||
140 | /** |
||||
141 | * Returns available object types to list as endpoints |
||||
142 | * |
||||
143 | * @return array Array of object type names |
||||
144 | */ |
||||
145 | protected function objectTypesEndpoints() |
||||
146 | { |
||||
147 | $allTypes = TableRegistry::get('ObjectTypes') |
||||
148 | ->find('list', ['keyField' => 'name', 'valueField' => 'is_abstract']) |
||||
149 | ->where(['enabled' => true]) |
||||
150 | ->toArray(); |
||||
151 | $endPoints = []; |
||||
152 | foreach ($allTypes as $t => $abstract) { |
||||
153 | $endPoints['/' . $t] = [ |
||||
154 | 'methods' => $abstract ? ['GET', 'DELETE'] : 'ALL', |
||||
155 | 'object_type' => true, |
||||
156 | 'multiple_types' => $abstract, |
||||
157 | ]; |
||||
158 | } |
||||
159 | |||||
160 | return $endPoints; |
||||
161 | } |
||||
162 | |||||
163 | /** |
||||
164 | * Check Authorization on endpoint |
||||
165 | * |
||||
166 | * @param string $endpoint Endpoint URI |
||||
167 | * @param string $method HTTP method |
||||
168 | * @return bool True on granted authorization, false otherwise |
||||
169 | */ |
||||
170 | protected function checkAuthorization($endpoint, $method) |
||||
171 | { |
||||
172 | if (empty(LoggedUser::getUser()) && !$this->unloggedAuthorized($endpoint, $method)) { |
||||
173 | return false; |
||||
174 | } |
||||
175 | |||||
176 | $environment = ['REQUEST_METHOD' => $method]; |
||||
177 | $uri = new Uri($endpoint); |
||||
178 | $request = new ServerRequest(compact('environment', 'uri')); |
||||
179 | $authorize = $this->Auth->getAuthorize('BEdita/API.Endpoint'); |
||||
180 | |||||
181 | return $authorize->authorize(LoggedUser::getUser(), $request); |
||||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * Default unlogged authorization on endpoint method, without permissions check |
||||
186 | * |
||||
187 | * @param string $endpoint Endpoint URI |
||||
188 | * @param string $method HTTP method |
||||
189 | * @return bool True on granted authorization, false otherwise |
||||
190 | */ |
||||
191 | protected function unloggedAuthorized($endpoint, $method) |
||||
192 | { |
||||
193 | $defaultAllow = Hash::get($this->defaultAllowUnlogged, $endpoint, $this->defaultAllowUnlogged['/*']); |
||||
194 | |||||
195 | return in_array($method, $defaultAllow); |
||||
196 | } |
||||
197 | } |
||||
198 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.