Passed
Pull Request — master (#39)
by Matthias
08:57
created

FileOperationController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 8
c 1
b 1
f 0
nc 1
nop 9
dl 0
loc 20
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * @copyright Copyright (c) 2018 Matthias Held <[email protected]>
5
 * @author Matthias Held <[email protected]>
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace OCA\RansomwareDetection\Controller;
23
24
use OCA\RansomwareDetection\Monitor;
25
use OCA\RansomwareDetection\Classifier;
26
use OCA\RansomwareDetection\AppInfo\Application;
27
use OCA\RansomwareDetection\Db\FileOperation;
28
use OCA\RansomwareDetection\Service\FileOperationService;
29
use OCA\Files_Trashbin\Trashbin;
0 ignored issues
show
Bug introduced by
The type OCA\Files_Trashbin\Trashbin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use OCA\Files_Trashbin\Helper;
0 ignored issues
show
Bug introduced by
The type OCA\Files_Trashbin\Helper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use OCP\AppFramework\Http;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use OCP\AppFramework\Http\JSONResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\JSONResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use OCP\AppFramework\Controller;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Controller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use OCP\Files\File;
0 ignored issues
show
Bug introduced by
The type OCP\Files\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use OCP\Files\Folder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\Folder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use OCP\IConfig;
0 ignored issues
show
Bug introduced by
The type OCP\IConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
use OCP\IUserSession;
0 ignored issues
show
Bug introduced by
The type OCP\IUserSession was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
use OCP\IRequest;
0 ignored issues
show
Bug introduced by
The type OCP\IRequest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
use OCP\ILogger;
0 ignored issues
show
Bug introduced by
The type OCP\ILogger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
40
41
class FileOperationController extends Controller
42
{
43
    /** @var IConfig */
44
    protected $config;
45
46
    /** @var IUserSession */
47
    protected $userSession;
48
49
    /** @var ILogger */
50
    protected $logger;
51
52
    /** @var Folder */
53
    protected $userFolder;
54
55
    /** @var FileOperationService */
56
    protected $service;
57
58
    /** @var Classifier */
59
    protected $classifier;
60
61
    /** @var string */
62
    protected $userId;
63
64
    /**
65
     * @param string               $appName
66
     * @param IRequest             $request
67
     * @param IUserSession         $userSession
68
     * @param IConfig              $config
69
     * @param ILogger              $logger
70
     * @param Folder               $userFolder
71
     * @param FileOperationService $service
72
     * @param Classifier           $classifier
73
     * @param string               $userId
74
     */
75
    public function __construct(
76
        $appName,
77
        IRequest $request,
78
        IUserSession $userSession,
79
        IConfig $config,
80
        ILogger $logger,
81
        Folder $userFolder,
82
        FileOperationService $service,
83
        Classifier $classifier,
84
        $userId
85
    ) {
86
        parent::__construct($appName, $request);
87
88
        $this->config = $config;
89
        $this->userSession = $userSession;
90
        $this->userFolder = $userFolder;
91
        $this->logger = $logger;
92
        $this->service = $service;
93
        $this->classifier = $classifier;
94
        $this->userId = $userId;
95
    }
96
97
    /**
98
     * Lists the files.
99
     *
100
     * @NoAdminRequired
101
     * @NoCSRFRequired
102
     *
103
     * @return JSONResponse
104
     */
105
    public function findAll()
106
    {
107
        $files = $this->service->findAll();
108
109
        foreach ($files as $file) {
110
            $this->classifier->classifyFile($file);
111
        }
112
113
        return new JSONResponse($files, Http::STATUS_OK);
114
    }
115
116
    /**
117
     * Find file with id.
118
     *
119
     * @NoAdminRequired
120
     * @NoCSRFRequired
121
     *
122
     * @return JSONResponse
123
     */
124
    public function find($id)
125
    {
126
        $file = $this->service->find($id);
127
128
        $this->classifier->classifyFile($file);
129
130
        return new JSONResponse($file, Http::STATUS_OK);
131
    }
132
133
    /**
134
     * Recover files from trashbin or remove them from normal storage.
135
     *
136
     * @NoAdminRequired
137
     * @NoCSRFRequired
138
     *
139
     * @param array $ids file operation id
140
     *
141
     * @return JSONResponse
142
     */
143
    public function recover($ids)
144
    {
145
        $deleted = 0;
146
        $recovered = 0;
147
        $filesRecovered = array();
148
        $error = false;
149
        $badRequest = false;
150
151
        foreach ($ids as $id) {
152
            try {
153
                $file = $this->service->find($id);
154
                switch ($file->getCommand()) {
155
                    case Monitor::WRITE:
156
                        // Recover new created files by deleting them
157
                        $filePath = $file->getPath().'/'.$file->getOriginalName();
158
                        if ($this->deleteFromStorage($filePath)) {
159
                            $this->service->deleteById($id, true);
160
161
                            $deleted++;
162
                            array_push($filesRecovered, $id);
163
                        } else {
164
                            // File cannot be deleted
165
                            $error = true;
166
                        }
167
                        break;
168
                    case Monitor::DELETE:
169
                        // Recover deleted files by restoring them from the trashbin
170
                        // It's not necessary to use the real path
171
                        $dir = '/';
172
                        $candidate = $this->findCandidateToRestore($dir, $file->getOriginalName());
173
                        if ($candidate !== null) {
174
                            $path = $dir.'/'.$candidate['name'].'.d'.$candidate['mtime'];
175
                            if (Trashbin::restore($path, $candidate['name'], $candidate['mtime']) !== false) {
176
                                $this->service->deleteById($id, true);
177
178
                                $recovered++;
179
                                array_push($filesRecovered, $id);
180
                            }
181
                            // File does not exist
182
                            $badRequest = false;
183
                        } else {
184
                            // No candidate found
185
                            $badRequest = false;
186
                        }
187
                        break;
188
                    case Monitor::RENAME:
189
                        $this->service->deleteById($id, true);
190
191
                        $deleted++;
192
                        array_push($filesRecovered, $id);
193
                        break;
194
                    case Monitor::CREATE:
195
                        // Recover new created files/folders
196
                        $filePath = $file->getPath().'/'.$file->getOriginalName();
197
                        if ($this->deleteFromStorage($filePath)) {
198
                            $this->service->deleteById($id, true);
199
200
                            $deleted++;
201
                            array_push($filesRecovered, $id);
202
                        } else {
203
                            // File cannot be deleted
204
                            $error = true;
205
                        }
206
                        break;
207
                    default:
208
                        // All other commands need no recovery
209
                        $this->service->deleteById($id, false);
210
211
                        $deleted++;
212
                        array_push($filesRecovered, $id);
213
                        break;
214
                    }
215
            } catch (\OCP\AppFramework\Db\MultipleObjectsReturnedException $exception) {
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Db\Mult...bjectsReturnedException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
216
                // Found more than one with the same file name
217
                $this->logger->debug('recover: Found more than one with the same file name.', array('app' => Application::APP_ID));
218
219
                $badRequest = false;
220
            } catch (\OCP\AppFramework\Db\DoesNotExistException $exception) {
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Db\DoesNotExistException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
221
                // Nothing found
222
                $this->logger->debug('recover: Files does not exist.', array('app' => Application::APP_ID));
223
224
                $badRequest = false;
225
            }
226
        }
227
        if ($error) {
228
            return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_INTERNAL_SERVER_ERROR);
229
        }
230
        if ($badRequest) {
0 ignored issues
show
introduced by
The condition $badRequest is always false.
Loading history...
231
            return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_BAD_REQUEST);
232
        }
233
        return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_OK);
234
    }
235
236
    /**
237
     * Deletes a file from the storage.
238
     *
239
     * @param string $path
240
     *
241
     * @return bool
242
     */
243
    private function deleteFromStorage($path)
244
    {
245
        try {
246
            $node = $this->userFolder->get($path);
247
            if ($node->isDeletable()) {
248
                $node->delete();
249
            } else {
250
                return false;
251
            }
252
253
            return true;
254
        } catch (\OCP\Files\NotFoundException $exception) {
0 ignored issues
show
Bug introduced by
The type OCP\Files\NotFoundException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
255
            // Nothing found
256
            $this->logger->debug('deleteFromStorage: Not found exception.', array('app' => Application::APP_ID));
257
258
            return true;
259
        }
260
    }
261
262
    /**
263
     * Finds a candidate to restore if a file with the specific does not exist.
264
     *
265
     * @param string $dir
266
     * @param string $fileName
267
     *
268
     * @return FileInfo
0 ignored issues
show
Bug introduced by
The type OCA\RansomwareDetection\Controller\FileInfo was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
269
     */
270
    private function findCandidateToRestore($dir, $fileName)
271
    {
272
        $files = array();
273
        $trashBinFiles = $this->getTrashFiles($dir);
274
275
        foreach ($trashBinFiles as $trashBinFile) {
276
            if (strcmp($trashBinFile['name'], $fileName) === 0) {
277
                $files[] = $trashBinFile;
278
            }
279
        }
280
281
        return array_pop($files);
282
    }
283
284
    /**
285
     * Workaround for testing.
286
     *
287
     * @param string $dir
288
     *
289
     * @return array
290
     */
291
    private function getTrashFiles($dir)
292
    {
293
        return Helper::getTrashFiles($dir, $this->userId, 'mtime', false);
294
    }
295
296
}