Passed
Push — master ( 82c165...9440db )
by Nils
10:41
created

ItemController   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 269
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 156
dl 0
loc 269
rs 9.44
c 2
b 0
f 0
wmc 37

4 Methods

Rating   Name   Duplication   Size   Complexity  
B inFoldersAction() 0 81 9
B getAction() 0 58 11
B createAction() 0 62 6
B checkNewItemData() 0 34 11
1
<?php
2
/**
3
 * Teampass - a collaborative passwords manager.
4
 * ---
5
 * This library is distributed in the hope that it will be useful,
6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8
 * ---
9
 *
10
 * @project   Teampass
11
 * @version    API
12
 *
13
 * @file      ItemControler.php
14
 * ---
15
 *
16
 * @author    Nils Laumaillé ([email protected])
17
 *
18
 * @copyright 2009-2024 Teampass.net
19
 *
20
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
21
 * ---
22
 *
23
 * @see       https://www.teampass.net
24
 */
25
26
use Symfony\Component\HttpFoundation\Request AS symfonyRequest;
27
28
class ItemController extends BaseController
29
{
30
31
32
    /**
33
     * Manage case inFolder - get items inside an array of folders
34
     *
35
     * @param array $userData
36
     */
37
    public function inFoldersAction(array $userData): void
38
    {
39
        $request = symfonyRequest::createFromGlobals();
40
        $requestMethod = $request->getMethod();
41
        $strErrorDesc = $responseData = $strErrorHeader = '';
42
43
        // get parameters
44
        $arrQueryStringParams = $this->getQueryStringParams();
45
46
        if (strtoupper($requestMethod) === 'GET') {
47
            // define WHERE clause
48
            $sqlExtra = '';
49
            if (empty($userData['folders_list']) === false) {
50
                $userData['folders_list'] = explode(',', $userData['folders_list']);
51
            } else {
52
                $userData['folders_list'] = [];
53
            }
54
55
            // SQL where clause with folders list
56
            if (isset($arrQueryStringParams['folders']) === true) {
57
                // convert the folders to an array
58
                $arrQueryStringParams['folders'] = explode(',', str_replace( array('[',']') , ''  , $arrQueryStringParams['folders']));
59
60
                // ensure to only use the intersection
61
                $foldersList = implode(',', array_intersect($arrQueryStringParams['folders'], $userData['folders_list']));
62
63
                // build sql where clause
64
                if (!empty($foldersList)) {
65
                    // build sql where clause
66
                    $sqlExtra = ' WHERE id_tree IN ('.$foldersList.')';
67
                } else {
68
                    // Send error
69
                    $this->sendOutput(
70
                        json_encode(['error' => 'Folders are mandatory']),
71
                        ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
72
                    );
73
                }
74
            } else {
75
                // Send error
76
                $this->sendOutput(
77
                    json_encode(['error' => 'Folders are mandatory']),
78
                    ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
79
                );
80
            }
81
82
            // SQL LIMIT
83
            $intLimit = 0;
84
            if (isset($arrQueryStringParams['limit']) === true) {
85
                $intLimit = $arrQueryStringParams['limit'];
86
            }
87
88
            // send query
89
            try {
90
                $itemModel = new ItemModel();
91
92
                $arrItems = $itemModel->getItems($sqlExtra, $intLimit, $userData['private_key'], $userData['id']);
93
                if (!empty($arrItems)) {
94
                    $responseData = json_encode($arrItems);
95
                } else {
96
                    $strErrorDesc = 'No content for this label';
97
                    $strErrorHeader = 'HTTP/1.1 204 No Content';
98
                }
99
            } catch (Error $e) {
100
                $strErrorDesc = $e->getMessage().'. Something went wrong! Please contact support.4';
101
                $strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
102
            }
103
        } else {
104
            $strErrorDesc = 'Method not supported';
105
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
106
        }
107
108
        // send output
109
        if (empty($strErrorDesc) === true) {
110
            $this->sendOutput(
111
                $responseData,
112
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
113
            );
114
        } else {
115
            $this->sendOutput(
116
                json_encode(['error' => $strErrorDesc]), 
117
                ['Content-Type: application/json', $strErrorHeader]
118
            );
119
        }
120
    }
121
    //end InFoldersAction()
122
123
    private function checkNewItemData(array $arrQueryStringParams, array $userData): array
124
    {
125
        if (isset($arrQueryStringParams['label']) === true
126
            && isset($arrQueryStringParams['folder_id']) === true
127
            && isset($arrQueryStringParams['password']) === true
128
            && isset($arrQueryStringParams['login']) === true
129
            && isset($arrQueryStringParams['email']) === true
130
            && isset($arrQueryStringParams['url']) === true
131
            && isset($arrQueryStringParams['tags']) === true
132
            && isset($arrQueryStringParams['anyone_can_modify']) === true
133
        ) {
134
            //
135
            if (in_array($arrQueryStringParams['folder_id'], $userData['folders_list']) === false) {
136
                return [
137
                    'error' => true,
138
                    'strErrorDesc' => 'User is not allowed in this folder',
139
                    'strErrorHeader' => 'HTTP/1.1 401 Unauthorized',
140
                ];
141
            } else if (empty($arrQueryStringParams['label']) === true) {
142
                return [
143
                    'error' => true,
144
                    'strErrorDesc' => 'Label is mandatory',
145
                    'strErrorHeader' => 'HTTP/1.1 401 Expected parameters not provided',
146
                ];
147
            } else {
148
                return [
149
                    'error' => false,
150
                ];
151
            }
152
        } else {
153
            return [
154
                'error' => true,
155
                'strErrorDesc' => 'All fields have to be provided even if empty (refer to documentation).',
156
                'strErrorHeader' => 'HTTP/1.1 401 Expected parameters not provided',
157
            ];
158
        }
159
    }
160
161
    /**
162
     * Manage case Add
163
     *
164
     * @param array $userData
165
     */
166
    public function createAction(array $userData)
167
    {
168
        $request = symfonyRequest::createFromGlobals();
169
        $requestMethod = $request->getMethod();
170
        $strErrorDesc = $strErrorHeader = '';
171
172
        if (strtoupper($requestMethod) === 'POST') {
173
            // Is user allowed to create a folder
174
            // We check if read_only is false
175
            if ((int) $userData['read_only'] === 1) {
176
                $strErrorDesc = 'User is not allowed to create an item';
177
                $strErrorHeader = 'HTTP/1.1 401 Unauthorized';
178
            } else {
179
                if (empty($userData['folders_list']) === false) {
180
                    $userData['folders_list'] = explode(',', $userData['folders_list']);
181
                } else {
182
                    $userData['folders_list'] = [];
183
                }
184
185
                // get parameters
186
                $arrQueryStringParams = $this->getQueryStringParams();
187
188
                // check parameters
189
                $arrCheck = $this->checkNewItemData($arrQueryStringParams, $userData);
0 ignored issues
show
Bug introduced by
It seems like $arrQueryStringParams can also be of type string; however, parameter $arrQueryStringParams of ItemController::checkNewItemData() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

189
                $arrCheck = $this->checkNewItemData(/** @scrutinizer ignore-type */ $arrQueryStringParams, $userData);
Loading history...
190
                if ($arrCheck['error'] === true) {
191
                    $strErrorDesc = $arrCheck['strErrorDesc'];
192
                    $strErrorHeader = $arrCheck['strErrorHeader'];
193
                } else {
194
                    // launch
195
                    $itemModel = new ItemModel();
196
                    $ret = $itemModel->addItem(
197
                        $arrQueryStringParams['folder_id'],
198
                        $arrQueryStringParams['label'],
199
                        $arrQueryStringParams['password'],
200
                        $arrQueryStringParams['description'],
201
                        $arrQueryStringParams['login'],
202
                        $arrQueryStringParams['email'],
203
                        $arrQueryStringParams['url'],
204
                        $arrQueryStringParams['tags'],
205
                        $arrQueryStringParams['anyone_can_modify'],
206
                        $arrQueryStringParams['icon'],
207
                        $userData['id'],
208
                        $userData['username'],
209
                    );
210
                    $responseData = json_encode($ret);
211
                }
212
            }
213
        } else {
214
            $strErrorDesc = 'Method not supported';
215
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
216
        }
217
218
        // send output
219
        if (empty($strErrorDesc) === true) {
220
            $this->sendOutput(
221
                $responseData,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $responseData does not seem to be defined for all execution paths leading up to this point.
Loading history...
222
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
223
            );
224
        } else {
225
            $this->sendOutput(
226
                json_encode(['error' => $strErrorDesc]),
227
                ['Content-Type: application/json', $strErrorHeader]
228
            );
229
        }
230
    }
231
    //end addAction()
232
233
234
    /**
235
     * Manage case get - get an item
236
     *
237
     * @param array $userData
238
     */
239
    public function getAction(array $userData): void
240
    {
241
        
242
        $request = symfonyRequest::createFromGlobals();
243
        $requestMethod = $request->getMethod();
244
        $strErrorDesc = '';
245
        $sqlExtra = '';
246
        $responseData = '';
247
        $strErrorHeader = '';
248
        $sql_constraint = ' AND (i.id_tree IN ('.$userData['folders_list'].') OR i.id IN ('.$userData['restricted_items_list'].'))';
249
250
        // get parameters
251
        $arrQueryStringParams = $this->getQueryStringParams();
252
253
        if (strtoupper($requestMethod) === 'GET') {
254
            // SQL where clause with item id
255
            if (isset($arrQueryStringParams['id']) === true) {
256
                // build sql where clause by ID
257
                $sqlExtra = ' WHERE i.id = '.$arrQueryStringParams['id'] . $sql_constraint;
258
            } else if (isset($arrQueryStringParams['label']) === true) {
259
                // build sql where clause by LABEL
260
                $sqlExtra = ' WHERE i.label '.(isset($arrQueryStringParams['like']) === true && (int) $arrQueryStringParams['like'] === 1 ? ' LIKE '.$arrQueryStringParams['label'] : ' = '.$arrQueryStringParams['label']) . $sql_constraint;
261
            } else if (isset($arrQueryStringParams['description']) === true) {
262
                // build sql where clause by LABEL
263
                $sqlExtra = ' WHERE i.description '.(isset($arrQueryStringParams['like']) === true && (int) $arrQueryStringParams['like'] === 1 ? ' LIKE '.$arrQueryStringParams['description'] : ' = '.$arrQueryStringParams['description']).$sql_constraint;
264
            } else {
265
                // Send error
266
                $this->sendOutput(
267
                    json_encode(['error' => 'Item id, label or description is mandatory']),
268
                    ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
269
                );
270
            }
271
272
            // send query
273
            try {
274
                $itemModel = new ItemModel();
275
276
                $arrItems = $itemModel->getItems($sqlExtra, 0, $userData['private_key'], $userData['id']);
277
                $responseData = json_encode($arrItems);
278
            } catch (Error $e) {
279
                $strErrorDesc = $e->getMessage().'. Something went wrong! Please contact support.6';
280
                $strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
281
            }
282
        } else {
283
            $strErrorDesc = 'Method not supported';
284
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
285
        }
286
287
        // send output
288
        if (empty($strErrorDesc) === true) {
289
            $this->sendOutput(
290
                $responseData,
291
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
292
            );
293
        } else {
294
            $this->sendOutput(
295
                json_encode(['error' => $strErrorDesc]), 
296
                ['Content-Type: application/json', $strErrorHeader]
297
            );
298
        }
299
    }
300
    //end getAction() 
301
}