Issues (98)

src/Control/HealthCheckController.php (9 issues)

1
<?php
2
3
namespace Sunnysideup\HealthCheckProvider\Control;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Core\Environment;
7
use Sunnysideup\HealthCheckProvider\Model\HealthCheckProvider;
8
use Sunnysideup\HealthCheckProvider\Model\HealthCheckProviderSecurity;
9
10
class HealthCheckController extends Controller
11
{
12
    protected $editorID = 0;
13
14
    private static $url_segment = 'health-check-provider';
0 ignored issues
show
The private property $url_segment is not used, and could be removed.
Loading history...
15
16
    private static $allowed_actions = [
0 ignored issues
show
The private property $allowed_actions is not used, and could be removed.
Loading history...
17
        'ping' => '->canProvide',
18
        'provide' => '->canProvide',
19
        'confirmreceipt' => '->canProvide',
20
    ];
21
22
    public function index($request)
0 ignored issues
show
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

22
    public function index(/** @scrutinizer ignore-unused */ $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
23
    {
24
        return $this->httpError(404);
25
    }
26
27
    public function ping()
28
    {
29
        $this->getResponse()->addHeader('Content-type', 'application/json');
30
        return '{"Success": ' . ($this->canProvide() ? 'true' : 'false') . '}';
31
    }
32
33
    public function provide($request)
34
    {
35
        $check = $this->checkSecurity($request);
36
        if ($check !== 'all-good') {
37
            return $check;
38
        }
39
40
        //we are ready!~
41
        $this->getResponse()->addHeader('Content-type', 'application/json');
42
        return $this->provideData();
43
    }
44
45
    public function confirmreceipt($request)
46
    {
47
        $check = $this->checkSecurity($request);
48
        if ($check !== 'all-good') {
49
            return $check;
50
        }
51
52
        $outcome = $this->recordReceipt($request);
53
54
        $this->getResponse()->addHeader('Content-type', 'application/json');
55
56
        return '{"Success": ' . $outcome . '}';
57
    }
58
59
    protected function provideData(): string
60
    {
61
        $obj = HealthCheckProvider::create();
62
        $obj->EditorID = $this->editorID;
63
        $obj->SendNow = true;
64
        $id = $obj->write();
65
        sleep(2);
66
        HealthCheckProvider::get()->byID($id);
67
        return (string) $obj->Data;
68
    }
69
70
    protected function recordReceipt($request): bool
71
    {
72
        $success = false;
73
        $id = (int) $request->param('ID');
74
        $code = $request->param('OtherID');
75
        /** @var HealthCheckProvider|null $obj */
76
        $obj = HealthCheckProvider::get()->byID($id);
77
        if ($obj) {
0 ignored issues
show
$obj is of type Sunnysideup\HealthCheckP...del\HealthCheckProvider, thus it always evaluated to true.
Loading history...
78
            if (! $code) {
79
                $code = 'no code provided';
80
            }
81
            $obj->ResponseCode = $code;
0 ignored issues
show
Bug Best Practice introduced by
The property ResponseCode does not exist on Sunnysideup\HealthCheckP...del\HealthCheckProvider. Since you implemented __set, consider adding a @property annotation.
Loading history...
82
            $obj->Sent = true;
0 ignored issues
show
Bug Best Practice introduced by
The property Sent does not exist on Sunnysideup\HealthCheckP...del\HealthCheckProvider. Since you implemented __set, consider adding a @property annotation.
Loading history...
83
            $obj->SendNow = false;
0 ignored issues
show
Bug Best Practice introduced by
The property SendNow does not exist on Sunnysideup\HealthCheckP...del\HealthCheckProvider. Since you implemented __set, consider adding a @property annotation.
Loading history...
84
            $obj->write();
85
            $success = $obj->getCodesMatch();
86
        }
87
88
        return $success;
89
    }
90
91
    protected function checkSecurity($request)
92
    {
93
        $headers = $request->getHeaders();
94
        $key = $headers['handshake'] ?? '';
95
        $ip = $request->getIp();
96
        $outcome = HealthCheckProviderSecurity::check($key, $ip);
97
        if ($outcome) {
98
            $this->editorID = HealthCheckProviderSecurity::get_editor_id($key, $ip);
99
100
            return 'all-good';
101
        }
102
        return $this->httpError(403, 'Sorry, we can not provide access.');
103
    }
104
105
    protected function canProvide(): bool
106
    {
107
        if (Environment::getEnv('SS_HEALTH_CHECK_PROVIDER_ALLOW_RETRIEVAL')) {
108
            return true;
109
        }
110
        die('Please set SS_HEALTH_CHECK_PROVIDER_ALLOW_RETRIEVAL to use this facility.');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
111
    }
112
}
113