Passed
Push — hypernext ( 403616...d6fe90 )
by Nico
11:05
created

web/app/controllers/RequestHandler.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * @author Nicolas CARPi <[email protected]>
4
 * @copyright 2012 Nicolas CARPi
5
 * @see https://www.elabftw.net Official website
6
 * @license AGPL-3.0
7
 * @package elabftw
8
 */
9
declare(strict_types=1);
10
11
namespace Elabftw\Elabftw;
12
13
use function dirname;
14
use Elabftw\Exceptions\DatabaseErrorException;
15
use Elabftw\Exceptions\FilesystemErrorException;
16
use Elabftw\Exceptions\IllegalActionException;
17
use Elabftw\Exceptions\ImproperActionException;
18
use Elabftw\Exceptions\ResourceNotFoundException;
19
use Elabftw\Exceptions\UnauthorizedException;
20
use Elabftw\Models\AbstractEntity;
21
use Elabftw\Models\ApiKeys;
22
use Elabftw\Models\Experiments;
23
use Elabftw\Models\ItemsTypes;
24
use Elabftw\Models\Status;
25
use Elabftw\Models\Tags;
26
use Elabftw\Models\Teams;
27
use Exception;
28
use PDOException;
29
use Swift_TransportException;
30
use Symfony\Component\HttpFoundation\JsonResponse;
31
use Symfony\Component\HttpFoundation\RedirectResponse;
32
33
require_once dirname(__DIR__) . '/init.inc.php';
34
35
$Response = new JsonResponse();
36
$Response->setData(array(
37
    'res' => false,
38
    'msg' => Tools::error(),
39
));
40
$res = '';
41
42
try {
43
    if ($Request->headers->get('Content-Type') === 'application/json') {
44
        $Processor = new JsonProcessor($App->Users, $Request);
45
    } elseif ($Request->getMethod() === 'GET') {
46
        $Processor = new RequestProcessor($App->Users, $Request);
47
    } else {
48
        $Processor = new FormProcessor($App->Users, $Request);
49
    }
50
51
    $action = $Processor->getAction();
52
    $Model = $Processor->getModel();
53
    $Params = $Processor->getParams();
54
    $target = $Processor->getTarget();
55
56
57
    // all non read actions for status and items types are limited to admins
58
    if ($action !== 'read' &&
59
        ($Model instanceof Status || $Model instanceof ItemsTypes) &&
60
        !$App->Session->get('is_admin')
61
        ) {
62
        throw new IllegalActionException('Non admin user tried to edit status or items types.');
63
    }
64
65
    if ($action === 'create') {
66
        $res = $Model->create($Params);
67
        if ($Model instanceof ApiKeys) {
68
            $res = $Params->getKey();
69
        }
70
    } elseif ($action === 'read') {
71
        $res = $Model->read($Params);
0 ignored issues
show
It seems like $Params can also be of type null; however, parameter $params of Elabftw\Models\Users::read() does only seem to accept Elabftw\Interfaces\ContentParamsInterface, 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

71
        $res = $Model->read(/** @scrutinizer ignore-type */ $Params);
Loading history...
72
    } elseif ($action === 'update') {
73
        // TODO should not exist, but it's here for now
74
        if ($Model instanceof ItemsTypes && ($target !== 'metadata')) {
75
            $res = $Model->updateAll($Params);
76
        } else {
77
            $res = $Model->update($Params);
78
        }
79
    } elseif ($action === 'destroy') {
80
        if ($Model instanceof Experiments) {
81
            $Teams = new Teams($App->Users);
82
            $teamConfigArr = $Teams->read(new ContentParams());
83
            if ((!$teamConfigArr['deletable_xp'] && !$App->Session->get('is_admin'))
84
                || $App->Config->configArr['deletable_xp'] === '0') {
85
                throw new ImproperActionException('You cannot delete experiments!');
86
            }
87
        }
88
        $res = $Model->destroy();
89
    } elseif ($action === 'duplicate' && $Model instanceof AbstractEntity) {
90
        $res = $Model->duplicate();
91
    } elseif ($action === 'deduplicate' && $Model instanceof Tags) {
92
        $res = $Model->deduplicate();
93
    } elseif ($action === 'lock' && $Model instanceof AbstractEntity) {
94
        $res = $Model->toggleLock();
95
    }
96
97
    if ($Processor instanceof FormProcessor) {
98
        $Response = new RedirectResponse('../../' . $Processor->Entity->page . '.php?mode=edit&id=' . $Processor->Entity->id);
99
        $Response->send();
100
        exit;
101
    }
102
    $Response->setData(array(
103
        'res' => true,
104
        'msg' => _('Saved'),
105
        'value' => $res,
106
    ));
107
} catch (Swift_TransportException $e) {
108
    // for swift error, don't display error to user as it might contain sensitive information
109
    // but log it and display general error. See #841
110
    $App->Log->error('', array('exception' => $e));
111
    $Response = new JsonResponse();
112
    $Response->setData(array(
113
        'res' => false,
114
        'msg' => _('Error sending email'),
115
    ));
116
} catch (ImproperActionException | UnauthorizedException | ResourceNotFoundException | PDOException $e) {
117
    $Response->setData(array(
118
        'res' => false,
119
        'msg' => $e->getMessage(),
120
    ));
121
} catch (IllegalActionException $e) {
122
    $App->Log->notice('', array(array('userid' => $App->Session->get('userid')), array('IllegalAction', $e)));
123
    $Response->setData(array(
124
        'res' => false,
125
        'msg' => Tools::error(true),
126
    ));
127
} catch (DatabaseErrorException | FilesystemErrorException $e) {
128
    $App->Log->error('', array(array('userid' => $App->Session->get('userid')), array('Error', $e)));
129
    $Response = new JsonResponse();
130
    $Response->setData(array(
131
        'res' => false,
132
        'msg' => $e->getMessage(),
133
    ));
134
} catch (Exception $e) {
135
    $App->Log->error('', array(array('userid' => $App->Session->get('userid') ?? 'anon'), array('Exception' => $e)));
136
    $Response->setData(array(
137
        'res' => false,
138
        'msg' => Tools::error(),
139
    ));
140
} finally {
141
    $Response->send();
142
}
143