ConfigGeneralController::saveAction()   D
last analyzed

Complexity

Conditions 20
Paths 101

Size

Total Lines 130
Code Lines 88

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 20
eloc 88
c 1
b 0
f 0
nc 101
nop 0
dl 0
loc 130
rs 4.1583

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Modules\Web\Controllers;
26
27
use Exception;
28
use RuntimeException;
29
use SP\Config\ConfigUtil;
30
use SP\Core\Acl\Acl;
31
use SP\Core\Acl\UnauthorizedPageException;
32
use SP\Core\Context\SessionContext;
33
use SP\Core\Events\Event;
34
use SP\Core\Events\EventMessage;
35
use SP\Core\Exceptions\SessionTimeout;
36
use SP\Core\Exceptions\SPException;
37
use SP\Http\JsonResponse;
38
use SP\Modules\Web\Controllers\Traits\ConfigTrait;
39
use SP\Services\Config\ConfigBackupService;
40
use SP\Storage\File\FileHandler;
41
use SP\Util\Util;
42
43
/**
44
 * Class ConfigGeneral
45
 *
46
 * @package SP\Modules\Web\Controllers
47
 */
48
final class ConfigGeneralController extends SimpleControllerBase
49
{
50
    use ConfigTrait;
51
52
    /**
53
     * saveAction
54
     *
55
     * @throws SPException
56
     */
57
    public function saveAction()
58
    {
59
        $this->checkSecurityToken($this->previousSk, $this->request);
60
61
        $configData = $this->config->getConfigData();
62
        $eventMessage = EventMessage::factory();
63
64
        // General
65
        $siteLang = $this->request->analyzeString('sitelang');
66
        $siteTheme = $this->request->analyzeString('sitetheme', 'material-blue');
67
        $sessionTimeout = $this->request->analyzeInt('session_timeout', 300);
68
        $applicationUrl = $this->request->analyzeString('app_url');
69
        $httpsEnabled = $this->request->analyzeBool('https_enabled', false);
70
        $debugEnabled = $this->request->analyzeBool('debug_enabled', false);
71
        $maintenanceEnabled = $this->request->analyzeBool('maintenance_enabled', false);
72
        $checkUpdatesEnabled = $this->request->analyzeBool('check_updates_enabled', false);
73
        $checkNoticesEnabled = $this->request->analyzeBool('check_notices_enabled', false);
74
        $encryptSessionEnabled = $this->request->analyzeBool('encrypt_session_enabled', false);
75
76
        $configData->setSiteLang($siteLang);
77
        $configData->setSiteTheme($siteTheme);
78
        $configData->setSessionTimeout($sessionTimeout);
79
        $configData->setApplicationUrl($applicationUrl);
80
        $configData->setHttpsEnabled($httpsEnabled);
81
        $configData->setDebug($debugEnabled);
82
        $configData->setMaintenance($maintenanceEnabled);
83
        $configData->setCheckUpdates($checkUpdatesEnabled);
84
        $configData->setChecknotices($checkNoticesEnabled);
85
        $configData->setEncryptSession($encryptSessionEnabled);
86
87
        // Events
88
        $logEnabled = $this->request->analyzeBool('log_enabled', false);
89
        $syslogEnabled = $this->request->analyzeBool('syslog_enabled', false);
90
        $remoteSyslogEnabled = $this->request->analyzeBool('remotesyslog_enabled', false);
91
        $syslogServer = $this->request->analyzeString('remotesyslog_server');
92
        $syslogPort = $this->request->analyzeInt('remotesyslog_port', 0);
93
94
        $configData->setLogEnabled($logEnabled);
95
        $configData->setLogEvents($this->request->analyzeArray('log_events', function ($items) {
0 ignored issues
show
Bug introduced by
It seems like $this->request->analyzeA...{ /* ... */ }, array()) can also be of type null; however, parameter $logEvents of SP\Config\ConfigData::setLogEvents() 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

95
        $configData->setLogEvents(/** @scrutinizer ignore-type */ $this->request->analyzeArray('log_events', function ($items) {
Loading history...
96
            return ConfigUtil::eventsAdapter($items);
97
        }, []));
98
99
        $configData->setSyslogEnabled($syslogEnabled);
100
101
        if ($remoteSyslogEnabled) {
102
            if (!$syslogServer || !$syslogPort) {
103
                return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Missing remote syslog parameters'));
104
            }
105
106
            $configData->setSyslogRemoteEnabled(true);
107
            $configData->setSyslogServer($syslogServer);
108
            $configData->setSyslogPort($syslogPort);
109
110
            if ($configData->isSyslogRemoteEnabled() === false) {
111
                $eventMessage->addDescription(__u('Remote syslog enabled'));
112
            }
113
        } elseif ($remoteSyslogEnabled === false && $configData->isSyslogRemoteEnabled()) {
114
            $configData->setSyslogRemoteEnabled(false);
115
116
            $eventMessage->addDescription(__u('Remote syslog disabled'));
117
        }
118
119
        // Proxy
120
        $proxyEnabled = $this->request->analyzeBool('proxy_enabled', false);
121
        $proxyServer = $this->request->analyzeString('proxy_server');
122
        $proxyPort = $this->request->analyzeInt('proxy_port', 8080);
123
        $proxyUser = $this->request->analyzeString('proxy_user');
124
        $proxyPass = $this->request->analyzeEncrypted('proxy_pass');
125
126
127
        // Valores para Proxy
128
        if ($proxyEnabled && (!$proxyServer || !$proxyPort)) {
129
            return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Missing Proxy parameters '));
130
        }
131
132
        if ($proxyEnabled) {
133
            $configData->setProxyEnabled(true);
134
            $configData->setProxyServer($proxyServer);
135
            $configData->setProxyPort($proxyPort);
136
            $configData->setProxyUser($proxyUser);
137
138
            if ($proxyPass !== '***') {
139
                $configData->setProxyPass($proxyPass);
140
            }
141
142
            if ($configData->isProxyEnabled() === false) {
143
                $eventMessage->addDescription(__u('Proxy enabled'));
144
            }
145
        } elseif ($proxyEnabled === false && $configData->isProxyEnabled()) {
146
            $configData->setProxyEnabled(false);
147
148
            $eventMessage->addDescription(__u('Proxy disabled'));
149
        }
150
151
        // Autentificación
152
        $authBasicEnabled = $this->request->analyzeBool('authbasic_enabled', false);
153
        $authBasicAutologinEnabled = $this->request->analyzeBool('authbasicautologin_enabled', false);
154
        $authBasicDomain = $this->request->analyzeString('authbasic_domain');
155
        $authSsoDefaultGroup = $this->request->analyzeInt('sso_defaultgroup');
156
        $authSsoDefaultProfile = $this->request->analyzeInt('sso_defaultprofile');
157
158
        // Valores para Autentificación
159
        if ($authBasicEnabled) {
160
            $configData->setAuthBasicEnabled(true);
161
            $configData->setAuthBasicAutoLoginEnabled($authBasicAutologinEnabled);
162
            $configData->setAuthBasicDomain($authBasicDomain);
163
            $configData->setSsoDefaultGroup($authSsoDefaultGroup);
164
            $configData->setSsoDefaultProfile($authSsoDefaultProfile);
165
166
            if ($configData->isAuthBasicEnabled() === false) {
167
                $eventMessage->addDescription(__u('Auth Basic enabled'));
168
            }
169
        } elseif ($authBasicEnabled === false && $configData->isAuthBasicEnabled()) {
170
            $configData->setAuthBasicEnabled(false);
171
            $configData->setAuthBasicAutoLoginEnabled(false);
172
173
            $eventMessage->addDescription(__u('Auth Basic disabled'));
174
        }
175
176
        return $this->saveConfig(
177
            $configData,
178
            $this->config,
179
            function () use ($eventMessage, $configData) {
180
                if ($configData->isMaintenance()) {
181
                    Util::lockApp($this->session->getUserData()->getId(), 'config');
182
                }
183
184
                $this->eventDispatcher->notifyEvent(
185
                    'save.config.general',
186
                    new Event($this, $eventMessage)
187
                );
188
            }
189
        );
190
    }
191
192
    /**
193
     * @return bool
194
     * @throws SPException
195
     */
196
    public function downloadLogAction()
197
    {
198
        $this->checkSecurityToken($this->previousSk, $this->request);
199
200
        if ($this->configData->isDemoEnabled()) {
201
            return __('Ey, this is a DEMO!!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return __('Ey, this is a DEMO!!') returns the type string which is incompatible with the documented return type boolean.
Loading history...
202
        }
203
204
        try {
205
            SessionContext::close();
206
207
            $file = new FileHandler(LOG_FILE);
208
            $file->checkFileExists();
209
210
            $this->eventDispatcher->notifyEvent('download.logFile',
211
                new Event($this, EventMessage::factory()
212
                    ->addDescription(__u('File downloaded'))
213
                    ->addDetail(__u('File'), str_replace(APP_ROOT, '', $file->getFile())))
214
            );
215
216
            $response = $this->router->response();
217
            $response->header('Cache-Control', 'max-age=60, must-revalidate');
218
            $response->header('Content-length', $file->getFileSize());
219
            $response->header('Content-type', $file->getFileType());
220
            $response->header('Content-Description', ' sysPass file');
221
            $response->header('Content-transfer-encoding', 'chunked');
222
            $response->header('Content-Disposition', 'attachment; filename="' . basename($file->getFile()) . '"');
223
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
224
            $response->send();
225
226
            $file->readChunked();
227
        } catch (Exception $e) {
228
            processException($e);
229
230
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
231
        }
232
233
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type boolean.
Loading history...
234
    }
235
236
    /**
237
     * @param string $type
238
     *
239
     * @return bool
240
     * @throws SPException
241
     */
242
    public function downloadConfigBackupAction($type)
243
    {
244
        $this->checkSecurityToken($this->previousSk, $this->request);
245
246
        if ($this->configData->isDemoEnabled()) {
247
            return __('Ey, this is a DEMO!!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return __('Ey, this is a DEMO!!') returns the type string which is incompatible with the documented return type boolean.
Loading history...
248
        }
249
250
        try {
251
            $this->eventDispatcher->notifyEvent('download.configBackupFile',
252
                new Event($this, EventMessage::factory()
253
                    ->addDescription(__u('File downloaded'))
254
                    ->addDetail(__u('File'), 'config.json'))
255
            );
256
257
            $configBackupService = $this->dic->get(ConfigBackupService::class);
258
259
            switch ($type) {
260
                case 'json':
261
                    $data = ConfigBackupService::configToJson($configBackupService->getBackup());
262
                    break;
263
                default:
264
                    throw new RuntimeException('Not implemented');
265
            }
266
267
            $response = $this->router->response();
268
            $response->header('Cache-Control', 'max-age=60, must-revalidate');
269
            $response->header('Content-length', strlen($data));
270
            $response->header('Content-type', 'application/json');
271
            $response->header('Content-Description', ' sysPass file');
272
            $response->header('Content-transfer-encoding', 'chunked');
273
            $response->header('Content-Disposition', 'attachment; filename="config.json"');
274
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
275
            $response->header('Content-transfer-encoding', 'binary');
276
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
277
278
            $response->body($data);
279
            $response->send(true);
280
        } catch (Exception $e) {
281
            processException($e);
282
283
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
284
        }
285
286
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type boolean.
Loading history...
287
    }
288
289
    /**
290
     * @return bool
291
     * @throws SessionTimeout
292
     */
293
    protected function initialize()
294
    {
295
        try {
296
            $this->checks();
297
            $this->checkAccess(Acl::CONFIG_GENERAL);
298
        } catch (UnauthorizedPageException $e) {
299
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
300
301
            return $this->returnJsonResponseException($e);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->returnJsonResponseException($e) returns the type boolean which is incompatible with the return type mandated by SP\Modules\Web\Controlle...ollerBase::initialize() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
302
        }
303
304
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the return type mandated by SP\Modules\Web\Controlle...ollerBase::initialize() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
305
    }
306
}