ApiController   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 39
dl 0
loc 106
rs 10
c 1
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A debugEnabled() 0 11 2
A badApiCall() 0 12 1
A checkToken() 0 13 2
A __construct() 0 9 4
A jsonResponse() 0 12 1
1
<?php
2
3
/* Copyright (C) 2024      Rafael San José      <[email protected]>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace Alxarafe\Base\Controller;
20
21
use Alxarafe\Base\Config;
22
use Alxarafe\Base\Controller\Trait\DbTrait;
23
use Alxarafe\Lib\Auth;
24
use Alxarafe\Lib\Functions;
25
use Alxarafe\Lib\Messages;
26
use Alxarafe\Lib\Trans;
27
use CoreModules\Admin\Controller\ConfigController;
28
use CoreModules\Admin\Model\User;
29
use DebugBar\DebugBarException;
30
use Exception;
31
use Firebase\JWT\JWT;
32
use Firebase\JWT\Key;
33
34
/**
35
 * Class ApiController. The generic API controller contains what is necessary for any API controller
36
 *
37
 * @package Alxarafe\Base
38
 */
39
abstract class ApiController
40
{
41
    use DbTrait;
42
43
    /**
44
     * Contains the identified user
45
     *
46
     * @var User|null
47
     */
48
    public static ?User $user = null;
49
50
    /**
51
     * ApiController constructor.
52
     * @throws DebugBarException
53
     */
54
    public function __construct()
55
    {
56
        $config = Config::getConfig();
57
        if (!isset($config->db) || !static::connectDb($config->db)) {
58
            Functions::httpRedirect(ConfigController::url());
59
        }
60
61
        if (isset($_REQUEST['token'])) {
62
            static::checkToken();
63
        }
64
    }
65
66
    /**
67
     * Verifies the received token and loads the user associated with it.
68
     *
69
     * @return bool
70
     */
71
    public static function checkToken(): bool
72
    {
73
        $jwt = $_REQUEST['token'];
74
        $secret_key = Auth::getSecurityKey();
75
        try {
76
            $decoded = JWT::decode($jwt, new Key($secret_key, 'HS256'));
77
        } catch (Exception $e) {
78
            self::badApiCall(Trans::_('bad_secret_key'), 401);
79
            return false;
80
        }
81
82
        static::$user = User::where('name', $decoded->data->user)->first();
0 ignored issues
show
Documentation Bug introduced by
It seems like CoreModules\Admin\Model\...d->data->user)->first() can also be of type Illuminate\Database\Eloq...elations\HasManyThrough or Illuminate\Database\Eloq...Relations\HasOneThrough. However, the property $user is declared as type CoreModules\Admin\Model\User|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
83
        return static::$user !== null;
84
    }
85
86
    /**
87
     * Returns an erroneous API response and ends the execution of the call
88
     *
89
     * @param $response
90
     * @param $httpCode
91
     * @return void
92
     */
93
    final public static function badApiCall($response = 'Bad API call', $httpCode = 400)
94
    {
95
        $result = [
96
            'ok' => false,
97
            'status' => $httpCode,
98
            'response' => $response,
99
            'message' => Messages::getMessages(),
100
        ];
101
102
        http_response_code($httpCode);
103
        header('Content-Type: application/json');
104
        die(json_encode(static::debugEnabled($result)));
105
    }
106
107
    /**
108
     * Return true if debug is enabled in config
109
     *
110
     * @return array
111
     */
112
    private static function debugEnabled($info): array
113
    {
114
        $config = Config::getConfig();
115
        $debug = $config->security->debug ?? false;
116
117
        if (!$debug) {
118
            return $info;
119
        }
120
121
        return array_merge($info, [
122
            'debug' => debug_backtrace(),
123
        ]);
124
    }
125
126
    /**
127
     * Returns a successful API response and ends the execution of the application.
128
     *
129
     * @param $response
130
     * @param $httpCode
131
     * @return void
132
     */
133
    final public static function jsonResponse($response, $httpCode = 200, $result_message = 'result')
134
    {
135
        $result = [
136
            'ok' => true,
137
            'status' => $httpCode,
138
            $result_message => $response,
139
            'message' => Messages::getMessages(),
140
        ];
141
142
        http_response_code($httpCode);
143
        header('Content-Type: application/json');
144
        die(json_encode(static::debugEnabled($result)));
145
    }
146
}
147