ConfigEncryptionController::saveAction()   C
last analyzed

Complexity

Conditions 15
Paths 105

Size

Total Lines 118
Code Lines 73

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 73
c 1
b 0
f 0
nc 105
nop 0
dl 0
loc 118
rs 5.289

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 DI\DependencyException;
28
use DI\NotFoundException;
29
use Exception;
30
use SP\Core\Acl\Acl;
31
use SP\Core\Acl\UnauthorizedPageException;
32
use SP\Core\Crypt\Hash;
33
use SP\Core\Crypt\Session as CryptSession;
34
use SP\Core\Events\Event;
35
use SP\Core\Events\EventMessage;
36
use SP\Core\Exceptions\SessionTimeout;
37
use SP\Core\Exceptions\SPException;
38
use SP\Http\JsonResponse;
39
use SP\Modules\Web\Controllers\Traits\JsonTrait;
40
use SP\Repositories\NoSuchItemException;
41
use SP\Services\Config\ConfigService;
42
use SP\Services\Crypt\MasterPassService;
43
use SP\Services\Crypt\TemporaryMasterPassService;
44
use SP\Services\Crypt\UpdateMasterPassRequest;
45
use SP\Services\ServiceException;
46
use SP\Services\Task\TaskFactory;
47
48
/**
49
 * Class ConfigEncryptionController
50
 *
51
 * @package SP\Modules\Web\Controllers
52
 */
53
final class ConfigEncryptionController extends SimpleControllerBase
54
{
55
    use JsonTrait;
56
57
    /**
58
     * @return bool
59
     * @throws DependencyException
60
     * @throws NotFoundException
61
     * @throws NoSuchItemException
62
     * @throws ServiceException
63
     * @throws SPException
64
     */
65
    public function saveAction()
66
    {
67
        $this->checkSecurityToken($this->previousSk, $this->request);
68
69
        $mastePassService = $this->dic->get(MasterPassService::class);
70
71
        $currentMasterPass = $this->request->analyzeEncrypted('current_masterpass');
72
        $newMasterPass = $this->request->analyzeEncrypted('new_masterpass');
73
        $newMasterPassR = $this->request->analyzeEncrypted('new_masterpass_repeat');
74
        $confirmPassChange = $this->request->analyzeBool('confirm_masterpass_change', false);
75
        $noAccountPassChange = $this->request->analyzeBool('no_account_change', false);
76
        $taskId = $this->request->analyzeString('taskId');
77
78
        if (!$mastePassService->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) {
79
            return $this->returnJsonResponse(
80
                JsonResponse::JSON_SUCCESS_STICKY,
81
                __u('Master password updated'),
82
                [__u('Please, restart the session for update it')]
83
            );
84
        }
85
86
        if (empty($newMasterPass) || empty($currentMasterPass)) {
87
            return $this->returnJsonResponse(
88
                JsonResponse::JSON_ERROR,
89
                __u('Master password not entered')
90
            );
91
        }
92
93
        if ($confirmPassChange === false) {
94
            return $this->returnJsonResponse(
95
                JsonResponse::JSON_ERROR,
96
                __u('The password update must be confirmed')
97
            );
98
        }
99
100
        if ($newMasterPass === $currentMasterPass) {
101
            return $this->returnJsonResponse(
102
                JsonResponse::JSON_ERROR,
103
                __u('Passwords are the same')
104
            );
105
        }
106
107
        if ($newMasterPass !== $newMasterPassR) {
108
            return $this->returnJsonResponse(
109
                JsonResponse::JSON_ERROR,
110
                __u('Master passwords do not match')
111
            );
112
        }
113
114
        if (!$mastePassService->checkMasterPassword($currentMasterPass)) {
115
            return $this->returnJsonResponse(
116
                JsonResponse::JSON_ERROR,
117
                __u('The current master password does not match')
118
            );
119
        }
120
121
        if (!$this->config->getConfigData()->isMaintenance()) {
122
            return $this->returnJsonResponse(
123
                JsonResponse::JSON_WARNING,
124
                __u('Maintenance mode not enabled'),
125
                [__u('Please, enable it to avoid unwanted behavior from other sessions')]
126
            );
127
        }
128
129
        if ($this->config->getConfigData()->isDemoEnabled()) {
130
            return $this->returnJsonResponse(
131
                JsonResponse::JSON_WARNING,
132
                __u('Ey, this is a DEMO!!')
133
            );
134
        }
135
136
        $configService = $this->dic->get(ConfigService::class);
137
138
        if (!$noAccountPassChange) {
139
            try {
140
                $task = $taskId !== null ? TaskFactory::create(__FUNCTION__, $taskId) : null;
141
142
                $request = new UpdateMasterPassRequest(
143
                    $currentMasterPass,
144
                    $newMasterPass,
145
                    $configService->getByParam(MasterPassService::PARAM_MASTER_PASS_HASH),
146
                    $task
147
                );
148
149
                $this->eventDispatcher->notifyEvent('update.masterPassword.start', new Event($this));
150
151
                $mastePassService->changeMasterPassword($request);
152
153
                $this->eventDispatcher->notifyEvent('update.masterPassword.end', new Event($this));
154
            } catch (Exception $e) {
155
                processException($e);
156
157
                $this->eventDispatcher->notifyEvent('exception', new Event($e));
158
159
                return $this->returnJsonResponseException($e);
160
            } finally {
161
                if (isset($task)) {
162
                    TaskFactory::end($task);
163
                }
164
            }
165
        } else {
166
            try {
167
                $this->eventDispatcher->notifyEvent('update.masterPassword.hash', new Event($this));
168
169
                $mastePassService->updateConfig(Hash::hashKey($newMasterPass));
170
            } catch (Exception $e) {
171
                processException($e);
172
173
                $this->eventDispatcher->notifyEvent('exception', new Event($e));
174
175
                return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Error while saving the Master Password\'s hash'));
176
            }
177
        }
178
179
        return $this->returnJsonResponse(
180
            JsonResponse::JSON_SUCCESS_STICKY,
181
            __u('Master password updated'),
182
            [__u('Please, restart the session for update it')]
183
        );
184
    }
185
186
    /**
187
     * Refresh master password hash
188
     */
189
    public function refreshAction()
190
    {
191
        try {
192
            $this->checkSecurityToken($this->previousSk, $this->request);
193
194
            if ($this->config->getConfigData()->isDemoEnabled()) {
195
                return $this->returnJsonResponse(JsonResponse::JSON_WARNING, __u('Ey, this is a DEMO!!'));
196
            }
197
198
            $masterPassService = $this->dic->get(MasterPassService::class);
199
            $masterPassService->updateConfig(Hash::hashKey(CryptSession::getSessionKey($this->session)));
200
201
            $this->eventDispatcher->notifyEvent('refresh.masterPassword.hash',
202
                new Event($this, EventMessage::factory()->addDescription(__u('Master password hash updated'))));
203
204
            return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Master password hash updated'));
205
        } catch (Exception $e) {
206
            processException($e);
207
208
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
209
210
211
            return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Error while updating the master password hash'));
212
        }
213
    }
214
215
    /**
216
     * Create a temporary master pass
217
     */
218
    public function saveTempAction()
219
    {
220
        try {
221
            $this->checkSecurityToken($this->previousSk, $this->request);
222
223
            $temporaryMasterPassService = $this->dic->get(TemporaryMasterPassService::class);
224
            $key = $temporaryMasterPassService->create($this->request->analyzeInt('temporary_masterpass_maxtime', 3600));
225
226
            $groupId = $this->request->analyzeInt('temporary_masterpass_group', 0);
227
            $sendEmail = $this->configData->isMailEnabled()
228
                && $this->request->analyzeBool('temporary_masterpass_email');
229
230
            if ($sendEmail) {
231
                try {
232
                    if ($groupId > 0) {
233
                        $temporaryMasterPassService->sendByEmailForGroup($groupId, $key);
234
                    } else {
235
                        $temporaryMasterPassService->sendByEmailForAllUsers($key);
236
                    }
237
238
                    return $this->returnJsonResponse(
239
                        JsonResponse::JSON_SUCCESS,
240
                        __u('Temporary password generated'),
241
                        [__u('Email sent')]
242
                    );
243
                } catch (Exception $e) {
244
                    processException($e);
245
246
                    $this->eventDispatcher->notifyEvent('exception', new Event($e));
247
248
                    return $this->returnJsonResponse(
249
                        JsonResponse::JSON_WARNING,
250
                        __u('Temporary password generated'),
251
                        [__u('Error while sending the email')]
252
                    );
253
                }
254
            }
255
256
            return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Temporary password generated'));
257
        } catch (Exception $e) {
258
            processException($e);
259
260
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
261
262
            return $this->returnJsonResponseException($e);
263
        }
264
    }
265
266
    /**
267
     * @return bool
268
     * @throws SessionTimeout
269
     */
270
    protected function initialize()
271
    {
272
        try {
273
            $this->checks();
274
            $this->checkAccess(Acl::CONFIG_CRYPT);
275
        } catch (UnauthorizedPageException $e) {
276
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
277
278
            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...
279
        }
280
281
        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...
282
    }
283
}