AccountController   F
last analyzed

Complexity

Total Complexity 90

Size/Duplication

Total Lines 1060
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 480
dl 0
loc 1060
rs 2
c 0
b 0
f 0
wmc 90

24 Methods

Rating   Name   Duplication   Size   Complexity  
A viewHistoryAction() 0 42 5
A editPassAction() 0 42 5
A viewPassAction() 0 32 4
A saveCreateAction() 0 37 3
A getPasswordPreset() 0 10 3
A editAction() 0 45 5
A requestAccessAction() 0 31 5
A copyPassAction() 0 19 1
A viewPassHistoryAction() 0 30 4
A createAction() 0 35 5
A viewAction() 0 46 5
A indexAction() 0 16 2
A saveEditRestoreAction() 0 30 2
A saveEditAction() 0 39 3
A saveEditPassAction() 0 35 3
A saveCopyAction() 0 3 1
B viewLinkAction() 0 77 9
A deleteAction() 0 42 5
A copyAction() 0 43 5
A copyPassHistoryAction() 0 19 1
A searchAction() 0 19 2
A saveRequestAction() 0 54 5
A saveDeleteAction() 0 39 3
A initialize() 0 17 4

How to fix   Complexity   

Complex Class

Complex classes like AccountController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AccountController, and based on these observations, apply Extract Interface, too.

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 Defuse\Crypto\Exception\CryptoException;
28
use DI\DependencyException;
29
use DI\NotFoundException;
30
use Exception;
31
use Psr\Container\ContainerExceptionInterface;
32
use Psr\Container\NotFoundExceptionInterface;
33
use SP\Bootstrap;
34
use SP\Core\Acl\Acl;
35
use SP\Core\Acl\ActionsInterface;
36
use SP\Core\Context\SessionContext;
37
use SP\Core\Crypt\Vault;
38
use SP\Core\Events\Event;
39
use SP\Core\Events\EventMessage;
40
use SP\Core\Exceptions\ConstraintException;
41
use SP\Core\Exceptions\NoSuchPropertyException;
42
use SP\Core\Exceptions\QueryException;
43
use SP\Core\Exceptions\SessionTimeout;
44
use SP\Core\Exceptions\SPException;
45
use SP\Core\Exceptions\ValidationException;
46
use SP\Core\UI\ThemeIcons;
47
use SP\DataModel\AccountExtData;
48
use SP\DataModel\ItemPreset\Password;
49
use SP\Http\JsonResponse;
50
use SP\Http\Uri;
51
use SP\Modules\Web\Controllers\Helpers\Account\AccountHelper;
52
use SP\Modules\Web\Controllers\Helpers\Account\AccountHistoryHelper;
53
use SP\Modules\Web\Controllers\Helpers\Account\AccountPasswordHelper;
54
use SP\Modules\Web\Controllers\Helpers\Account\AccountSearchHelper;
55
use SP\Modules\Web\Controllers\Helpers\LayoutHelper;
56
use SP\Modules\Web\Controllers\Traits\ItemTrait;
57
use SP\Modules\Web\Controllers\Traits\JsonTrait;
58
use SP\Modules\Web\Forms\AccountForm;
59
use SP\Mvc\Controller\CrudControllerInterface;
60
use SP\Repositories\NoSuchItemException;
61
use SP\Services\Account\AccountAclService;
62
use SP\Services\Account\AccountHistoryService;
63
use SP\Services\Account\AccountService;
64
use SP\Services\Auth\AuthException;
65
use SP\Services\ItemPreset\ItemPresetInterface;
66
use SP\Services\ItemPreset\ItemPresetService;
67
use SP\Services\PublicLink\PublicLinkService;
68
use SP\Services\ServiceException;
69
use SP\Services\User\UserService;
70
use SP\Util\ErrorUtil;
71
use SP\Util\ImageUtil;
72
use SP\Util\Util;
73
74
/**
75
 * Class AccountController
76
 *
77
 * @package SP\Modules\Web\Controllers
78
 */
79
final class AccountController extends ControllerBase implements CrudControllerInterface
80
{
81
    use JsonTrait, ItemTrait;
0 ignored issues
show
introduced by
The trait SP\Modules\Web\Controllers\Traits\ItemTrait requires some properties which are not provided by SP\Modules\Web\Controllers\AccountController: $data, $key
Loading history...
82
83
    /**
84
     * @var AccountService
85
     */
86
    protected $accountService;
87
    /**
88
     * @var ThemeIcons
89
     */
90
    protected $icons;
91
92
    /**
93
     * Index action
94
     *
95
     * @throws ContainerExceptionInterface
96
     */
97
    public function indexAction()
98
    {
99
        try {
100
            $accountSearchHelper = $this->dic->get(AccountSearchHelper::class);
101
            $accountSearchHelper->getSearchBox();
102
            $accountSearchHelper->getAccountSearch();
103
104
            $this->eventDispatcher->notifyEvent('show.account.search', new Event($this));
105
106
            $this->view();
107
        } catch (Exception $e) {
108
            processException($e);
109
110
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
111
112
            ErrorUtil::showExceptionInView($this->view, $e);
113
        }
114
    }
115
116
    /**
117
     * Search action
118
     */
119
    public function searchAction()
120
    {
121
        try {
122
            $this->checkSecurityToken($this->previousSk, $this->request);
123
124
            $accountSearchHelper = $this->dic->get(AccountSearchHelper::class);
125
            $accountSearchHelper->getAccountSearch();
126
127
            $this->eventDispatcher->notifyEvent('show.account.search', new Event($this));
128
129
            return $this->returnJsonResponseData([
130
                'html' => $this->render()
131
            ]);
132
        } catch (Exception $e) {
133
            processException($e);
134
135
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
136
137
            return $this->returnJsonResponseException($e);
138
        }
139
    }
140
141
    /**
142
     * View action
143
     *
144
     * @param int $id Account's ID
145
     *
146
     * @throws ContainerExceptionInterface
147
     * @throws NotFoundExceptionInterface
148
     */
149
    public function viewAction($id)
150
    {
151
        try {
152
            $this->checkSecurityToken($this->previousSk, $this->request);
153
154
            $this->view->addTemplate('account');
155
156
            $accountDetailsResponse = $this->accountService->getById($id);
157
            $this->accountService
158
                ->withUsersById($accountDetailsResponse)
159
                ->withUserGroupsById($accountDetailsResponse)
160
                ->withTagsById($accountDetailsResponse);
161
162
            $accountHelper = $this->dic->get(AccountHelper::class);
163
            $accountHelper->setIsView(true);
164
            $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_VIEW);
165
166
            $this->view->assign('title',
167
                [
168
                    'class' => 'titleNormal',
169
                    'name' => __('Account Details'),
170
                    'icon' => $this->icons->getIconView()->getIcon()
171
                ]
172
            );
173
174
            $this->accountService->incrementViewCounter($id);
175
176
            $this->eventDispatcher->notifyEvent('show.account', new Event($this));
177
178
            if ($this->isAjax === false) {
179
                $this->upgradeView();
180
            }
181
182
            $this->view();
183
        } catch (Exception $e) {
184
            processException($e);
185
186
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
187
188
            if ($this->isAjax === false
189
                && !$this->view->isUpgraded()
190
            ) {
191
                $this->upgradeView();
192
            }
193
194
            ErrorUtil::showExceptionInView($this->view, $e, 'account');
195
        }
196
    }
197
198
    /**
199
     * View public link action
200
     *
201
     * @param string $hash Link's hash
202
     *
203
     * @throws ContainerExceptionInterface
204
     * @throws NotFoundExceptionInterface
205
     */
206
    public function viewLinkAction($hash)
207
    {
208
        try {
209
            // Set the security token to its previous value because we can't tell
210
            // the browser which will be the new security token (not so good...)
211
            $this->session->setSecurityKey($this->previousSk);
212
213
            $layoutHelper = $this->dic->get(LayoutHelper::class);
214
            $layoutHelper->getPublicLayout('account-link', 'account');
215
216
            $publicLinkService = $this->dic->get(PublicLinkService::class);
217
            $publicLinkData = $publicLinkService->getByHash($hash);
218
219
            if (time() < $publicLinkData->getDateExpire()
220
                && $publicLinkData->getCountViews() < $publicLinkData->getMaxCountViews()
221
            ) {
222
                $publicLinkService->addLinkView($publicLinkData);
223
224
                $this->accountService->incrementViewCounter($publicLinkData->getItemId());
225
                $this->accountService->incrementDecryptCounter($publicLinkData->getItemId());
226
227
                /** @var Vault $vault */
228
                $vault = unserialize($publicLinkData->getData());
229
230
                /** @var AccountExtData $accountData */
231
                $accountData = Util::unserialize(AccountExtData::class, $vault->getData($publicLinkService->getPublicLinkKey($publicLinkData->getHash())->getKey()));
232
233
                $this->view->assign('title',
234
                    [
235
                        'class' => 'titleNormal',
236
                        'name' => __('Account Details'),
237
                        'icon' => $this->icons->getIconView()->getIcon()
238
                    ]
239
                );
240
241
                $this->view->assign('isView', true);
242
                $this->view->assign('useImage', $this->configData->isPublinksImageEnabled() || $this->configData->isAccountPassToImage());
243
244
                if ($this->view->useImage) {
0 ignored issues
show
Bug Best Practice introduced by
The property useImage does not exist on SP\Mvc\View\Template. Since you implemented __get, consider adding a @property annotation.
Loading history...
245
                    $imageUtil = $this->dic->get(ImageUtil::class);
246
                    $this->view->assign('accountPassImage', $imageUtil->convertText($accountData->getPass()));
247
                } else {
248
                    $this->view->assign('copyPassRoute', Acl::getActionRoute(Acl::ACCOUNT_VIEW_PASS));
249
                }
250
251
                $this->view->assign('accountData', $accountData);
252
253
                $clientAddress = $this->configData->isDemoEnabled() ? '***' : $this->request->getClientAddress(true);
254
255
                $baseUrl = ($this->configData->getApplicationUrl() ?: Bootstrap::$WEBURI) . Bootstrap::$SUBURI;
256
257
                $deepLink = new Uri($baseUrl);
258
                $deepLink->addParam('r', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW) . '/' . $accountData->getId());
259
260
                $this->eventDispatcher->notifyEvent('show.account.link',
261
                    new Event($this, EventMessage::factory()
262
                        ->addDescription(__u('Link viewed'))
263
                        ->addDetail(__u('Account'), $accountData->getName())
264
                        ->addDetail(__u('Client'), $accountData->getClientName())
265
                        ->addDetail(__u('Agent'), $this->request->getHeader('User-Agent'))
266
                        ->addDetail(__u('HTTPS'), $this->request->isHttps() ? __u('ON') : __u('OFF'))
267
                        ->addDetail(__u('IP'), $clientAddress)
268
                        ->addDetail(__u('Link'), $deepLink->getUriSigned($this->configData->getPasswordSalt()))
269
                        ->addExtra('userId', $publicLinkData->getUserId())
270
                        ->addExtra('notify', $publicLinkData->isNotify()))
271
                );
272
            } else {
273
                ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION, true, 'account-link');
274
            }
275
276
            $this->view();
277
        } catch (Exception $e) {
278
            processException($e);
279
280
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
281
282
            ErrorUtil::showExceptionInView($this->view, $e, 'account-link');
283
        }
284
    }
285
286
    /**
287
     * Create action
288
     */
289
    public function createAction()
290
    {
291
        try {
292
            $this->checkSecurityToken($this->previousSk, $this->request);
293
294
            $accountHelper = $this->dic->get(AccountHelper::class);
295
            $accountHelper->setViewForBlank(Acl::ACCOUNT_CREATE);
296
297
            $this->view->addTemplate('account');
298
            $this->view->assign('title',
299
                [
300
                    'class' => 'titleGreen',
301
                    'name' => __('New Account'),
302
                    'icon' => $this->icons->getIconAdd()->getIcon()
303
                ]
304
            );
305
            $this->view->assign('formRoute', 'account/saveCreate');
306
307
            $this->eventDispatcher->notifyEvent('show.account.create', new Event($this));
308
309
            if ($this->isAjax === false) {
310
                $this->upgradeView();
311
            }
312
313
            $this->view();
314
        } catch (Exception $e) {
315
            processException($e);
316
317
            if ($this->isAjax === false
318
                && !$this->view->isUpgraded()
319
            ) {
320
                $this->upgradeView();
321
            }
322
323
            ErrorUtil::showExceptionInView($this->view, $e, 'account');
324
        }
325
    }
326
327
    /**
328
     * Copy action
329
     *
330
     * @param int $id Account's ID
331
     *
332
     * @throws ContainerExceptionInterface
333
     * @throws NotFoundExceptionInterface
334
     */
335
    public function copyAction($id)
336
    {
337
        try {
338
            $this->checkSecurityToken($this->previousSk, $this->request);
339
340
            $accountDetailsResponse = $this->accountService->getById($id);
341
            $this->accountService
342
                ->withUsersById($accountDetailsResponse)
343
                ->withUserGroupsById($accountDetailsResponse)
344
                ->withTagsById($accountDetailsResponse);
345
346
            $accountHelper = $this->dic->get(AccountHelper::class);
347
            $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_COPY);
348
349
            $this->view->addTemplate('account');
350
            $this->view->assign('title',
351
                [
352
                    'class' => 'titleGreen',
353
                    'name' => __('New Account'),
354
                    'icon' => $this->icons->getIconAdd()->getIcon()
355
                ]
356
            );
357
            $this->view->assign('formRoute', 'account/saveCopy');
358
359
            $this->eventDispatcher->notifyEvent('show.account.copy', new Event($this));
360
361
            if ($this->isAjax === false) {
362
                $this->upgradeView();
363
            }
364
365
            $this->view();
366
        } catch (Exception $e) {
367
            processException($e);
368
369
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
370
371
            if ($this->isAjax === false
372
                && !$this->view->isUpgraded()
373
            ) {
374
                $this->upgradeView();
375
            }
376
377
            ErrorUtil::showExceptionInView($this->view, $e, 'account');
378
        }
379
    }
380
381
    /**
382
     * Edit action
383
     *
384
     * @param int $id Account's ID
385
     *
386
     * @throws ContainerExceptionInterface
387
     * @throws NotFoundExceptionInterface
388
     */
389
    public function editAction($id)
390
    {
391
        try {
392
            $this->checkSecurityToken($this->previousSk, $this->request);
393
394
            $accountDetailsResponse = $this->accountService->getById($id);
395
            $this->accountService
396
                ->withUsersById($accountDetailsResponse)
397
                ->withUserGroupsById($accountDetailsResponse)
398
                ->withTagsById($accountDetailsResponse);
399
400
            $accountHelper = $this->dic->get(AccountHelper::class);
401
            $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_EDIT);
402
403
            $this->view->addTemplate('account');
404
            $this->view->assign('title',
405
                [
406
                    'class' => 'titleOrange',
407
                    'name' => __('Edit Account'),
408
                    'icon' => $this->icons->getIconEdit()->getIcon()
409
                ]
410
            );
411
            $this->view->assign('formRoute', 'account/saveEdit');
412
413
            $this->accountService->incrementViewCounter($id);
414
415
            $this->eventDispatcher->notifyEvent('show.account.edit', new Event($this));
416
417
            if ($this->isAjax === false) {
418
                $this->upgradeView();
419
            }
420
421
            $this->view();
422
        } catch (Exception $e) {
423
            processException($e);
424
425
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
426
427
            if ($this->isAjax === false
428
                && !$this->view->isUpgraded()
429
            ) {
430
                $this->upgradeView();
431
            }
432
433
            ErrorUtil::showExceptionInView($this->view, $e, 'account');
434
        }
435
    }
436
437
    /**
438
     * Delete action
439
     *
440
     * @param int $id Account's ID
441
     *
442
     * @throws ContainerExceptionInterface
443
     * @throws NotFoundExceptionInterface
444
     */
445
    public function deleteAction($id = null)
446
    {
447
        try {
448
            $this->checkSecurityToken($this->previousSk, $this->request);
449
450
            $accountDetailsResponse = $this->accountService->getById($id);
451
            $this->accountService
452
                ->withUsersById($accountDetailsResponse)
453
                ->withUserGroupsById($accountDetailsResponse);
454
455
            $accountHelper = $this->dic->get(AccountHelper::class);
456
            $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_DELETE);
457
458
            $this->view->addTemplate('account');
459
            $this->view->assign('title',
460
                [
461
                    'class' => 'titleRed',
462
                    'name' => __('Remove Account'),
463
                    'icon' => $this->icons->getIconDelete()->getIcon()
464
                ]
465
            );
466
            $this->view->assign('formRoute', 'account/saveDelete');
467
468
            $this->eventDispatcher->notifyEvent('show.account.delete', new Event($this));
469
470
            if ($this->isAjax === false) {
471
                $this->upgradeView();
472
            }
473
474
            $this->view();
475
        } catch (Exception $e) {
476
            processException($e);
477
478
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
479
480
            if ($this->isAjax === false
481
                && !$this->view->isUpgraded()
482
            ) {
483
                $this->upgradeView();
484
            }
485
486
            ErrorUtil::showExceptionInView($this->view, $e, 'account');
487
        }
488
    }
489
490
    /**
491
     * Obtener los datos para mostrar el interface para modificar la clave de cuenta
492
     *
493
     * @param int $id Account's ID
494
     *
495
     * @throws ContainerExceptionInterface
496
     * @throws NotFoundExceptionInterface
497
     */
498
    public function editPassAction($id)
499
    {
500
        try {
501
            $this->checkSecurityToken($this->previousSk, $this->request);
502
503
            $accountDetailsResponse = $this->accountService->getById($id);
504
            $this->accountService
505
                ->withUsersById($accountDetailsResponse)
506
                ->withUserGroupsById($accountDetailsResponse);
507
508
            $accountHelper = $this->dic->get(AccountHelper::class);
509
            $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_EDIT_PASS);
510
511
            $this->view->addTemplate('account-editpass');
512
            $this->view->assign('title',
513
                [
514
                    'class' => 'titleOrange',
515
                    'name' => __('Edit Account Password'),
516
                    'icon' => $this->icons->getIconEditPass()->getIcon()
517
                ]
518
            );
519
            $this->view->assign('formRoute', 'account/saveEditPass');
520
521
            $this->eventDispatcher->notifyEvent('show.account.editpass', new Event($this));
522
523
            if ($this->isAjax === false) {
524
                $this->upgradeView();
525
            }
526
527
            $this->view();
528
        } catch (Exception $e) {
529
            processException($e);
530
531
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
532
533
            if ($this->isAjax === false
534
                && !$this->view->isUpgraded()
535
            ) {
536
                $this->upgradeView();
537
            }
538
539
            ErrorUtil::showExceptionInView($this->view, $e, 'account-editpass');
540
        }
541
    }
542
543
    /**
544
     * Obtener los datos para mostrar el interface para ver cuenta en fecha concreta
545
     *
546
     * @param int $id Account's ID
547
     *
548
     * @throws ContainerExceptionInterface
549
     * @throws NotFoundExceptionInterface
550
     */
551
    public function viewHistoryAction($id)
552
    {
553
        try {
554
            $this->checkSecurityToken($this->previousSk, $this->request);
555
556
            $accountHistoryService = $this->dic->get(AccountHistoryService::class);
557
            $accountHistoryData = $accountHistoryService->getById($id);
558
559
            $accountHistoryHelper = $this->dic->get(AccountHistoryHelper::class);
560
            $accountHistoryHelper->setView($accountHistoryData, Acl::ACCOUNT_HISTORY_VIEW);
561
562
            $this->view->addTemplate('account-history');
563
564
            $this->view->assign('title',
565
                [
566
                    'class' => 'titleNormal',
567
                    'name' => __('Account Details'),
568
                    'icon' => 'access_time'
569
                ]
570
            );
571
572
            $this->view->assign('formRoute', 'account/saveRestore');
573
574
            $this->eventDispatcher->notifyEvent('show.account.history', new Event($this));
575
576
            if ($this->isAjax === false) {
577
                $this->upgradeView();
578
            }
579
580
            $this->view();
581
        } catch (Exception $e) {
582
            processException($e);
583
584
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
585
586
            if ($this->isAjax === false
587
                && !$this->view->isUpgraded()
588
            ) {
589
                $this->upgradeView();
590
            }
591
592
            ErrorUtil::showExceptionInView($this->view, $e, 'account-history');
593
        }
594
    }
595
596
    /**
597
     * Obtener los datos para mostrar el interface de solicitud de cambios en una cuenta
598
     *
599
     * @param int $id Account's ID
600
     *
601
     * @throws ContainerExceptionInterface
602
     * @throws NotFoundExceptionInterface
603
     */
604
    public function requestAccessAction($id)
605
    {
606
        try {
607
            $this->checkSecurityToken($this->previousSk, $this->request);
608
609
            $accountHelper = $this->dic->get(AccountHelper::class);
610
            $accountHelper->setIsView(true);
611
            $accountHelper->setViewForRequest($this->accountService->getById($id), Acl::ACCOUNT_REQUEST);
612
613
            $this->view->addTemplate('account-request');
614
            $this->view->assign('formRoute', 'account/saveRequest');
615
616
            $this->eventDispatcher->notifyEvent('show.account.request', new Event($this));
617
618
            if ($this->isAjax === false) {
619
                $this->upgradeView();
620
            }
621
622
            $this->view();
623
        } catch (Exception $e) {
624
            processException($e);
625
626
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
627
628
            if ($this->isAjax === false
629
                && !$this->view->isUpgraded()
630
            ) {
631
                $this->upgradeView();
632
            }
633
634
            ErrorUtil::showExceptionInView($this->view, $e, 'account-request');
635
        }
636
    }
637
638
    /**
639
     * Display account's password
640
     *
641
     * @param int $id Account's ID
642
     * @param int $parentId
643
     *
644
     * @return bool
645
     */
646
    public function viewPassAction($id, $parentId = 0)
647
    {
648
        try {
649
            $this->checkSecurityToken($this->previousSk, $this->request);
650
651
            $accountPassHelper = $this->dic->get(AccountPasswordHelper::class);
652
653
            $account = $this->accountService->getPasswordForId($id);
654
655
            $passwordPreset = $this->getPasswordPreset();
656
            $useImage = $this->configData->isAccountPassToImage()
657
                || $passwordPreset !== null && $passwordPreset->isUseImage();
658
659
            $this->view->assign('isLinked', $parentId > 0);
660
661
            $data = $accountPassHelper->getPasswordView($account, $useImage);
662
663
            $this->accountService->incrementDecryptCounter($id);
664
665
            $this->eventDispatcher->notifyEvent('show.account.pass',
666
                new Event($this, EventMessage::factory()
667
                    ->addDescription(__u('Password viewed'))
668
                    ->addDetail(__u('Account'), $account->getName()))
669
            );
670
671
            return $this->returnJsonResponseData($data);
672
        } catch (Exception $e) {
673
            processException($e);
674
675
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
676
677
            return $this->returnJsonResponseException($e);
678
        }
679
    }
680
681
    /**
682
     * @return Password
683
     * @throws DependencyException
684
     * @throws NotFoundException
685
     * @throws ConstraintException
686
     * @throws NoSuchPropertyException
687
     * @throws QueryException
688
     */
689
    private function getPasswordPreset()
690
    {
691
        $itemPreset = $this->dic->get(ItemPresetService::class)
692
            ->getForCurrentUser(ItemPresetInterface::ITEM_TYPE_ACCOUNT_PASSWORD);
693
694
        if ($itemPreset !== null && $itemPreset->getFixed() === 1) {
695
            return $itemPreset->hydrate(Password::class);
696
        }
697
698
        return null;
699
    }
700
701
    /**
702
     * Display account's password
703
     *
704
     * @param int $id Account's ID
705
     *
706
     * @return bool
707
     */
708
    public function viewPassHistoryAction($id)
709
    {
710
        try {
711
            $this->checkSecurityToken($this->previousSk, $this->request);
712
713
            $accountPassHelper = $this->dic->get(AccountPasswordHelper::class);
714
715
            $account = $this->accountService->getPasswordHistoryForId($id);
716
717
            $passwordPreset = $this->getPasswordPreset();
718
            $useImage = $this->configData->isAccountPassToImage()
719
                || $passwordPreset !== null && $passwordPreset->isUseImage();
720
721
            $this->view->assign('isLinked', 0);
722
723
            $data = $accountPassHelper->getPasswordView($account, $useImage);
724
725
            $this->eventDispatcher->notifyEvent('show.account.pass.history',
726
                new Event($this, EventMessage::factory()
727
                    ->addDescription(__u('Password viewed'))
728
                    ->addDetail(__u('Account'), $account->getName()))
729
            );
730
731
            return $this->returnJsonResponseData($data);
732
        } catch (Exception $e) {
733
            processException($e);
734
735
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
736
737
            return $this->returnJsonResponseException($e);
738
        }
739
    }
740
741
    /**
742
     * Copy account's password
743
     *
744
     * @param int $id Account's ID
745
     *
746
     * @return bool
747
     * @throws Helpers\HelperException
748
     * @throws DependencyException
749
     * @throws NotFoundException
750
     * @throws CryptoException
751
     * @throws ConstraintException
752
     * @throws QueryException
753
     * @throws NoSuchItemException
754
     * @throws ServiceException
755
     * @throws SPException
756
     */
757
    public function copyPassAction($id)
758
    {
759
        $this->checkSecurityToken($this->previousSk, $this->request);
760
761
        $accountPassHelper = $this->dic->get(AccountPasswordHelper::class);
762
763
        $account = $this->accountService->getPasswordForId($id);
764
765
        $data = [
766
            'accpass' => $accountPassHelper->getPasswordClear($account),
767
        ];
768
769
        $this->eventDispatcher->notifyEvent('copy.account.pass',
770
            new Event($this, EventMessage::factory()
771
                ->addDescription(__u('Password copied'))
772
                ->addDetail(__u('Account'), $account->getName()))
773
        );
774
775
        return $this->returnJsonResponseData($data);
776
    }
777
778
    /**
779
     * Copy account's password
780
     *
781
     * @param int $id Account's ID
782
     *
783
     * @return bool
784
     * @throws Helpers\HelperException
785
     * @throws DependencyException
786
     * @throws NotFoundException
787
     * @throws CryptoException
788
     * @throws ConstraintException
789
     * @throws QueryException
790
     * @throws NoSuchItemException
791
     * @throws ServiceException
792
     * @throws SPException
793
     */
794
    public function copyPassHistoryAction($id)
795
    {
796
        $this->checkSecurityToken($this->previousSk, $this->request);
797
798
        $accountPassHelper = $this->dic->get(AccountPasswordHelper::class);
799
800
        $account = $this->accountService->getPasswordHistoryForId($id);
801
802
        $data = [
803
            'accpass' => $accountPassHelper->getPasswordClear($account),
804
        ];
805
806
        $this->eventDispatcher->notifyEvent('copy.account.pass.history',
807
            new Event($this, EventMessage::factory()
808
                ->addDescription(__u('Password copied'))
809
                ->addDetail(__u('Account'), $account->getName()))
810
        );
811
812
        return $this->returnJsonResponseData($data);
813
    }
814
815
    /**
816
     * Saves copy action
817
     */
818
    public function saveCopyAction()
819
    {
820
        $this->saveCreateAction();
821
    }
822
823
    /**
824
     * Saves create action
825
     */
826
    public function saveCreateAction()
827
    {
828
        try {
829
            $this->checkSecurityToken($this->previousSk, $this->request);
830
831
            $form = new AccountForm($this->dic);
832
            $form->validate(Acl::ACCOUNT_CREATE);
833
834
            $accountId = $this->accountService->create($form->getItemData());
835
836
            $accountDetails = $this->accountService->getById($accountId)->getAccountVData();
837
838
            $this->eventDispatcher->notifyEvent('create.account',
839
                new Event($this, EventMessage::factory()
840
                    ->addDescription(__u('Account created'))
841
                    ->addDetail(__u('Account'), $accountDetails->getName())
842
                    ->addDetail(__u('Client'), $accountDetails->getClientName()))
843
            );
844
845
            $this->addCustomFieldsForItem(Acl::ACCOUNT, $accountId, $this->request);
846
847
            return $this->returnJsonResponseData(
848
                [
849
                    'itemId' => $accountId,
850
                    'nextAction' => Acl::getActionRoute(Acl::ACCOUNT_EDIT)
851
                ],
852
                JsonResponse::JSON_SUCCESS,
853
                __u('Account created')
854
            );
855
        } catch (ValidationException $e) {
856
            return $this->returnJsonResponseException($e);
857
        } catch (Exception $e) {
858
            processException($e);
859
860
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
861
862
            return $this->returnJsonResponseException($e);
863
        }
864
    }
865
866
    /**
867
     * Saves edit action
868
     *
869
     * @param $id Account's ID
0 ignored issues
show
Documentation Bug introduced by
The doc comment Account's at position 0 could not be parsed: Unknown type name 'Account's' at position 0 in Account's.
Loading history...
870
     *
871
     * @return bool
872
     */
873
    public function saveEditAction($id)
874
    {
875
        try {
876
            $this->checkSecurityToken($this->previousSk, $this->request);
877
878
            $form = new AccountForm($this->dic, $id);
879
            $form->validate(Acl::ACCOUNT_EDIT);
880
881
            $itemData = $form->getItemData();
882
883
            $this->accountService->update($itemData);
884
885
            $accountDetails = $this->accountService->getById($id)->getAccountVData();
886
887
            $this->eventDispatcher->notifyEvent('edit.account',
888
                new Event($this, EventMessage::factory()
889
                    ->addDescription(__u('Account updated'))
890
                    ->addDetail(__u('Account'), $accountDetails->getName())
891
                    ->addDetail(__u('Client'), $accountDetails->getClientName()))
892
            );
893
894
            $this->updateCustomFieldsForItem(Acl::ACCOUNT, $id, $this->request);
895
896
            return $this->returnJsonResponseData(
897
                [
898
                    'itemId' => $id,
899
                    'nextAction' => Acl::getActionRoute(Acl::ACCOUNT_VIEW)
900
                ],
901
                JsonResponse::JSON_SUCCESS,
902
                __u('Account updated')
903
            );
904
        } catch (ValidationException $e) {
905
            return $this->returnJsonResponseException($e);
906
        } catch (Exception $e) {
907
            processException($e);
908
909
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
910
911
            return $this->returnJsonResponseException($e);
912
        }
913
    }
914
915
    /**
916
     * Saves edit action
917
     *
918
     * @param $id Account's ID
0 ignored issues
show
Documentation Bug introduced by
The doc comment Account's at position 0 could not be parsed: Unknown type name 'Account's' at position 0 in Account's.
Loading history...
919
     *
920
     * @return bool
921
     */
922
    public function saveEditPassAction($id)
923
    {
924
        try {
925
            $this->checkSecurityToken($this->previousSk, $this->request);
926
927
            $form = new AccountForm($this->dic, $id);
928
            $form->validate(Acl::ACCOUNT_EDIT_PASS);
929
930
            $this->accountService->editPassword($form->getItemData());
931
932
            $accountDetails = $this->accountService->getById($id)->getAccountVData();
933
934
            $this->eventDispatcher->notifyEvent('edit.account.pass',
935
                new Event($this, EventMessage::factory()
936
                    ->addDescription(__u('Password updated'))
937
                    ->addDetail(__u('Account'), $accountDetails->getName())
938
                    ->addDetail(__u('Client'), $accountDetails->getClientName()))
939
            );
940
941
            return $this->returnJsonResponseData(
942
                [
943
                    'itemId' => $id,
944
                    'nextAction' => Acl::getActionRoute(Acl::ACCOUNT_VIEW)
945
                ],
946
                JsonResponse::JSON_SUCCESS,
947
                __u('Password updated')
948
            );
949
        } catch (ValidationException $e) {
950
            return $this->returnJsonResponseException($e);
951
        } catch (Exception $e) {
952
            processException($e);
953
954
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
955
956
            return $this->returnJsonResponseException($e);
957
        }
958
    }
959
960
    /**
961
     * Saves restore action
962
     *
963
     * @param int $historyId Account's history ID
964
     * @param int $id        Account's ID
965
     *
966
     * @return bool
967
     */
968
    public function saveEditRestoreAction($historyId, $id)
969
    {
970
        try {
971
            $this->checkSecurityToken($this->previousSk, $this->request);
972
973
            $this->accountService->editRestore($historyId, $id);
974
975
            $accountDetails = $this->accountService->getById($id)->getAccountVData();
976
977
            $this->eventDispatcher->notifyEvent('edit.account.restore',
978
                new Event($this, EventMessage::factory()
979
                    ->addDescription(__u('Account restored'))
980
                    ->addDetail(__u('Account'), $accountDetails->getName())
981
                    ->addDetail(__u('Client'), $accountDetails->getClientName()))
982
            );
983
984
            return $this->returnJsonResponseData(
985
                [
986
                    'itemId' => $id,
987
                    'nextAction' => Acl::getActionRoute(Acl::ACCOUNT_VIEW)
988
                ],
989
                JsonResponse::JSON_SUCCESS,
990
                __u('Account restored')
991
            );
992
        } catch (Exception $e) {
993
            processException($e);
994
995
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
996
997
            return $this->returnJsonResponseException($e);
998
        }
999
    }
1000
1001
    /**
1002
     * Saves delete action
1003
     *
1004
     * @param int $id Account's ID
1005
     *
1006
     * @return bool
1007
     */
1008
    public function saveDeleteAction($id)
1009
    {
1010
        try {
1011
            $this->checkSecurityToken($this->previousSk, $this->request);
1012
1013
            if ($id === null) {
0 ignored issues
show
introduced by
The condition $id === null is always false.
Loading history...
1014
                $this->accountService->deleteByIdBatch($this->getItemsIdFromRequest($this->request));
1015
1016
                $this->eventDispatcher->notifyEvent(
1017
                    'delete.account.selection',
1018
                    new Event($this, EventMessage::factory()
1019
                        ->addDescription(__u('Accounts removed')))
1020
                );
1021
1022
                $this->deleteCustomFieldsForItem(Acl::ACCOUNT, $id);
1023
1024
                return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Accounts removed'));
1025
            }
1026
1027
            $accountDetails = $this->accountService->getById($id)->getAccountVData();
1028
1029
            $this->accountService->delete($id);
1030
1031
            $this->eventDispatcher->notifyEvent('delete.account',
1032
                new Event($this, EventMessage::factory()
1033
                    ->addDescription(__u('Account removed'))
1034
                    ->addDetail(__u('Account'), $accountDetails->getName())
1035
                    ->addDetail(__u('Client'), $accountDetails->getClientName()))
1036
            );
1037
1038
            $this->deleteCustomFieldsForItem(Acl::ACCOUNT, $id);
1039
1040
            return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Account removed'));
1041
        } catch (Exception $e) {
1042
            processException($e);
1043
1044
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
1045
1046
            return $this->returnJsonResponseException($e);
1047
        }
1048
    }
1049
1050
    /**
1051
     * Saves a request action
1052
     *
1053
     * @param $id Account's ID
0 ignored issues
show
Documentation Bug introduced by
The doc comment Account's at position 0 could not be parsed: Unknown type name 'Account's' at position 0 in Account's.
Loading history...
1054
     *
1055
     * @return bool
1056
     */
1057
    public function saveRequestAction($id)
1058
    {
1059
        try {
1060
            $this->checkSecurityToken($this->previousSk, $this->request);
1061
1062
            $description = $this->request->analyzeString('description');
1063
1064
            if (empty($description)) {
1065
                throw new ValidationException(__u('A description is needed'));
1066
            }
1067
1068
            $accountDetails = $this->accountService->getById($id)->getAccountVData();
1069
1070
            $baseUrl = ($this->configData->getApplicationUrl() ?: Bootstrap::$WEBURI) . Bootstrap::$SUBURI;
1071
1072
            $deepLink = new Uri($baseUrl);
1073
            $deepLink->addParam('r', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW) . '/' . $id);
1074
1075
            $usersId = [$accountDetails->userId, $accountDetails->userEditId];
1076
1077
            $userService = $this->dic->get(UserService::class);
1078
1079
            $this->eventDispatcher->notifyEvent('request.account',
1080
                new Event($this, EventMessage::factory()
1081
                    ->addDescription(__u('Request'))
1082
                    ->addDetail(__u('Requester'), sprintf('%s (%s)', $this->userData->getName(), $this->userData->getLogin()))
1083
                    ->addDetail(__u('Account'), $accountDetails->getName())
1084
                    ->addDetail(__u('Client'), $accountDetails->getClientName())
1085
                    ->addDetail(__u('Description'), $description)
1086
                    ->addDetail(__u('Link'), $deepLink->getUriSigned($this->configData->getPasswordSalt()))
1087
                    ->addExtra('accountId', $id)
1088
                    ->addExtra('whoId', $this->userData->getId())
1089
                    ->setExtra('userId', $usersId)
1090
                    ->setExtra('email', array_map(function ($value) {
1091
                        return $value->email;
1092
                    }, $userService->getUserEmailById($usersId))))
1093
            );
1094
1095
            return $this->returnJsonResponseData(
1096
                [
1097
                    'itemId' => $id,
1098
                    'nextAction' => Acl::getActionRoute(Acl::ACCOUNT)
1099
                ],
1100
                JsonResponse::JSON_SUCCESS,
1101
                __u('Request done')
1102
            );
1103
        } catch (ValidationException $e) {
1104
            return $this->returnJsonResponseException($e);
1105
        } catch (Exception $e) {
1106
            processException($e);
1107
1108
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
1109
1110
            return $this->returnJsonResponseException($e);
1111
        }
1112
    }
1113
1114
    /**
1115
     * Initialize class
1116
     *
1117
     * @throws ContainerExceptionInterface
1118
     * @throws NotFoundExceptionInterface
1119
     * @throws AuthException
1120
     * @throws SessionTimeout
1121
     */
1122
    protected function initialize()
1123
    {
1124
        if ($this->actionName !== 'viewLinkAction') {
1125
            $this->checkLoggedIn();
1126
        }
1127
1128
        if (DEBUG === true
0 ignored issues
show
introduced by
The condition SP\Modules\Web\Controllers\DEBUG === true is always false.
Loading history...
1129
            && $this->session->getAppStatus() === SessionContext::APP_STATUS_RELOADED
1130
        ) {
1131
            $this->session->resetAppStatus();
1132
1133
            // Reset de los datos de ACL de cuentas
1134
            AccountAclService::clearAcl($this->session->getUserData()->getId());
1135
        }
1136
1137
        $this->accountService = $this->dic->get(AccountService::class);
1138
        $this->icons = $this->theme->getIcons();
1139
    }
1140
}