Completed
Push — master ( b97427...e235cc )
by Raffael
30:35 queued 26:08
created

Http::invalidAuthentication()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 0
cts 29
cp 0
rs 8.7697
c 0
b 0
f 0
cc 6
nc 5
nop 0
crap 42
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon\Bootstrap;
13
14
use Balloon\Hook;
15
use Balloon\Server;
16
use Micro\Auth\Adapter\None as AuthNone;
17
use Micro\Auth\Auth;
18
use Micro\Http\ExceptionInterface;
19
use Micro\Http\Response;
20
use Micro\Http\Router;
21
use MongoDB\BSON\Binary;
22
use Psr\Log\LoggerInterface;
23
24
class Http extends AbstractBootstrap
25
{
26
    /**
27
     * Auth.
28
     *
29
     * @var Auth
30
     */
31
    protected $auth;
32
33
    /**
34
     * Hook.
35
     *
36
     * @var Hook
37
     */
38
    protected $hook;
39
40
    /**
41
     * Router.
42
     *
43
     * @var Router
44
     */
45
    protected $router;
46
47
    /**
48
     * Server.
49
     *
50
     * @var Server
51
     */
52
    protected $server;
53
54
    /**
55
     * Http.
56
     */
57
    public function __construct(LoggerInterface $logger, Auth $auth, Hook $hook, Router $router, Server $server)
58
    {
59
        $this->setExceptionHandler();
60
        $this->setErrorHandler();
61
        $this->logger = $logger;
62
        $this->auth = $auth;
63
        $this->hook = $hook;
64
        $this->router = $router;
65
        $this->server = $server;
66
    }
67
68
    /**
69
     * Process.
70
     */
71
    public function process()
72
    {
73
        $this->logger->info('processing incoming http ['.$_SERVER['REQUEST_METHOD'].'] request to ['.$_SERVER['REQUEST_URI'].']', [
74
            'category' => get_class($this),
75
        ]);
76
77
        $this->hook->run('preAuthentication', [$this->auth]);
78
79
        if ($this->auth->requireOne()) {
80
            $this->hook->run('postAuthentication', [$this->auth, $this->auth->getIdentity()]);
81
82
            if (
83
                !($this->auth->getIdentity()->getAdapter() instanceof AuthNone)) {
0 ignored issues
show
Bug introduced by
The class Micro\Auth\Adapter\None does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
84
                $this->auth->getIdentity()->getAttributeMap()->addMapper('binary', function ($value) {
85
                    return new Binary($value, Binary::TYPE_GENERIC);
86
                });
87
88
                $this->server->setIdentity($this->auth->getIdentity());
89
            }
90
91
            $this->router->run();
92
        } else {
93
            $this->invalidAuthentication();
94
        }
95
96
        return $this;
97
    }
98
99
    /**
100
     * Send invalid authentication response.
101
     */
102
    protected function invalidAuthentication(): void
103
    {
104
        $this->hook->run('postAuthentication', [$this->auth, null]);
105
106
        if (isset($_SERVER['PHP_AUTH_USER']) && '_logout' === $_SERVER['PHP_AUTH_USER']) {
107
            (new Response())
108
                ->setCode(401)
109
                ->setBody([
110
                    'error' => 'Unauthorized',
111
                    'message' => 'authentication failed',
112
                ])
113
                ->send();
114
        } else {
115
            if ('/api/auth' === $_SERVER['PATH_INFO']) {
116
                $code = 403;
117
            } else {
118
                $code = 401;
119
            }
120
121
            $response = (new Response())
122
                ->setCode($code)
123
                ->setBody([
124
                    'error' => 'Unauthorized',
125
                    'message' => 'authentication failed',
126
                ]);
127
128
            if (!isset($_SERVER['HTTP_AUTHORIZATION']) || substr($_SERVER['HTTP_AUTHORIZATION'], 0, 5) === 'Basic') {
129
                $response->setHeader('WWW-Authenticate', 'Basic realm="balloon"');
130
            }
131
132
            $response->send();
133
        }
134
    }
135
136
    /**
137
     * Set exception handler.
138
     */
139
    protected function setExceptionHandler(): self
140
    {
141
        set_exception_handler(function ($e) {
142
            $this->logger->emergency('uncaught exception: '.$e->getMessage(), [
143
                'category' => get_class($this),
144
                'exception' => $e,
145
            ]);
146
147
            $code = 500;
148
            if ($e instanceof ExceptionInterface) {
0 ignored issues
show
Bug introduced by
The class Micro\Http\ExceptionInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
149
                $code = $e->getStatusCode();
150
            }
151
152
            (new Response())
153
                ->setCode($code)
154
                ->setBody([
155
                    'error' => get_class($e),
156
                    'message' => $e->getMessage(),
157
                ])
158
                ->send();
159
        });
160
161
        return $this;
162
    }
163
}
164