Passed
Push — Auth ( 9ea218...52ac6b )
by Stone
02:22
created

AjaxController::checkXlmRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Core;
4
5
use Core\JsonException;
6
7
8
/**
9
 * Class AjaxController
10
 * @package Core
11
 *
12
 * out parent controller for all ajax calls
13
 *
14
 */
15
abstract class AjaxController extends Controller
16
{
17
18
    /**
19
     * The request object to handle all gets and posts
20
     * @var Dependency\Request
21
     *
22
     */
23
    protected $request;
24
25
    /**
26
     * The response module to handle response messages
27
     * @var Dependency\Response
28
     */
29
    protected $response;
30
31
    protected $auth;
32
33
    /**
34
     * On construction, we imediatly check for security and bail out on the first sign of fraude
35
     * Only allow XmlHTTPRequests or throw an exception
36
     * Only allowed to call if Csrf token is valid or throw a json error
37
     * AjaxController constructor.
38
     * @param Container $container
39
     * @throws \Exception
40
     *
41
     */
42
    public function __construct(Container $container)
43
    {
44
        $this->loadModules[] = 'Auth';
45
        parent::__construct($container);
46
47
        $this->request = $container->getRequest(); //adding our request object as it will be needed in the ajax calls
48
        $this->response = $container->getResponse();
49
50
        //we only allow xmlHTTPRequests here for security
51
        $this->checkXlmRequest();
52
        $this->checkReferer();
53
        $this->csrf->checkJsonCsrf();
54
    }
55
56
    /**
57
     * checks if the call is made by an admin and throws an error if not.
58
     * @throws JsonException
59
     */
60
    protected function onlyAdmin()
61
    {
62
        if (!$this->auth->isAdmin()) {
63
            throw new JsonException('You do not have the rights to perform this action');
64
        }
65
    }
66
67
    /**
68
     * Checks if we have an Xml Http request and throws an error if not
69
     * @throws \ErrorException
70
     */
71
    private function checkXlmRequest(): void
72
    {
73
        if (!$this->request->isXmlRequest()) {
74
            throw new \ErrorException('Call not permitted', 404);
75
        }
76
    }
77
78
    /**
79
     * Check if the request is coming from the same domain as the base url of the site
80
     * @throws JsonException
81
     */
82
    private function checkReferer(): void
83
    {
84
85
        $referer = $this->request->getReferer();
86
        $baseUrl = $this->request->getBaseUrl();
87
        $inUrl = strpos($referer, $baseUrl);
88
        if ($inUrl === false || $inUrl > 0) { //not at start of referer
89
            if ($referer !== null) {//the referer can be null with certain navigators, so don't block on that
90
                throw new JsonException('Illegal referer.');
91
92
            }
93
94
        }
95
    }
96
97
    /**
98
     * Construct our json reply message
99
     * @param $message
100
     * @param int $code
101
     * @return string json encoded message
102
     */
103
    public function jsonResponse($message = null, $code = 200): string
104
    {
105
        // clear the old headers
106
        //header_remove(); //->this removes our csrf error checking so no go for the moment.
107
        // set the actual code
108
        http_response_code($code);
109
        // set the header to make sure cache is forced
110
        header("Cache-Control: no-transform,public,max-age=300,s-maxage=900");
111
        // treat this as json
112
        //header('Content-Type: application/json');
113
        $this->response->setHeaderContentType('json');
114
        $status = array(
115
            200 => '200 OK',
116
            400 => '400 Bad Request',
117
            422 => 'Unprocessable Entity',
118
            500 => '500 Internal Server Error'
119
        );
120
        // ok, validation error, or failure
121
        header('Status: ' . $status[$code]);
122
        // return the encoded json
123
        return json_encode(array(
124
            'status' => $code < 300, // success or not?
125
            'message' => $message
126
        ));
127
    }
128
129
    /**
130
     * Only allow post messages
131
     */
132
    protected function onlyPost()
133
    {
134
        //is post
135
        if (!$this->request->isPost()) {
136
            throw new JsonException('Call is not post');
137
        }
138
    }
139
140
141
}