Test Failed
Push — master ( 817d84...d52e3d )
by Raffael
05:44
created

Users::getWhoami()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
crap 2
nc 1
nop 1
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\App\Api\v2;
13
14
use Balloon\AttributeDecorator\Pager;
15
use Balloon\Server;
16
use Balloon\Server\AttributeDecorator;
17
use Balloon\Server\User;
18
use Balloon\Server\User\Exception;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Balloon\App\Api\v2\Exception.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
19
use Micro\Http\Response;
20
use MongoDB\BSON\Binary;
21
use function MongoDB\BSON\fromJSON;
22
use MongoDB\BSON\ObjectId;
23
use function MongoDB\BSON\toPHP;
24
25
class Users
26
{
27
    /**
28
     * User.
29
     *
30
     * @var User
31
     */
32
    protected $user;
33
34
    /**
35
     * Server.
36
     *
37
     * @var Server
38
     */
39
    protected $server;
40
41
    /**
42
     * Decorator.
43
     *
44
     * @var AttributeDecorator
45
     */
46
    protected $decorator;
47
48
    /**
49
     * Initialize.
50
     */
51
    public function __construct(Server $server, AttributeDecorator $decorator)
52
    {
53
        $this->user = $server->getIdentity();
54
        $this->server = $server;
55
        $this->decorator = $decorator;
56
    }
57
58
    /**
59
     * Get user instance.
60
     */
61
    public function _getUser(string $id, bool $require_admin = true): User
62
    {
63
        $user = $this->server->getUserById(new ObjectId($id));
64
65
        if ($user->getId() == $this->user->getId() || $require_admin === false) {
66
            return $user;
67
        }
68
69
        if ($this->user->isAdmin()) {
70
            return $user;
71
        }
72
73
        throw new Exception\NotAdmin('submitted parameters require admin privileges');
74
    }
75
76
    /**
77
     * Who am I?
78
     */
79
    public function getWhoami(array $attributes = []): Response
80
    {
81
        $result = $this->decorator->decorate($this->user, $attributes);
82
83
        return (new Response())->setCode(200)->setBody($result);
84
    }
85
86
    /**
87
     * Node attribute summary.
88
     */
89
    public function getNodeAttributeSummary(array $attributes = [], int $limit = 25): Response
90
    {
91
        $result = $this->user->getNodeAttributeSummary($attributes, $limit);
92
93
        return (new Response())->setCode(200)->setBody($result);
94
    }
95
96
    /**
97
     * Group membership.
98
     */
99
    public function getGroups(string $id, array $attributes = [], int $offset = 0, int $limit = 20): Response
100
    {
101
        $user = $this->_getUser($id);
102
        $result = $user->getResolvedGroups($offset, $limit);
103
        $uri = '/api/v2/users/'.$user->getId().'/groups';
104
        $pager = new Pager($this->decorator, $result, $attributes, $offset, $limit, $uri);
105
        $result = $pager->paging();
106
107
        return (new Response())->setCode(200)->setBody($result);
108
    }
109
110
    /**
111
     * User attributes.
112
     *
113
     * @param null|mixed $query
114
     */
115
    public function get(?string $id = null, $query = null, array $attributes = [], int $offset = 0, int $limit = 20): Response
116
    {
117
        if ($id === null) {
118
            if ($query === null) {
119
                $query = [];
120
            } elseif (is_string($query)) {
121
                $query = toPHP(fromJSON($query), [
122
                    'root' => 'array',
123
                    'document' => 'array',
124
                    'array' => 'array',
125
                ]);
126
            }
127
128
            $result = $this->server->getUsers($query, $offset, $limit);
129
            $pager = new Pager($this->decorator, $result, $attributes, $offset, $limit, '/api/v2/users');
130
            $result = $pager->paging();
131
        } else {
132
            $result = $this->decorator->decorate($this->_getUser($id, false), $attributes);
133
        }
134
135
        return (new Response())->setCode(200)->setBody($result);
136
    }
137
138
    /**
139
     * Get user avatar.
140
     */
141
    public function getAvatar(string $id): Response
142
    {
143
        $avatar = $this->_getUser($id, false)->getAttributes()['avatar'];
144
        if ($avatar instanceof Binary) {
0 ignored issues
show
Bug introduced by
The class MongoDB\BSON\Binary 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...
145
            return (new Response())
146
                ->setOutputFormat('text')
147
                ->setBody($avatar->getData())
148
                ->setHeader('Content-Type', 'image/png');
149
        }
150
151
        return (new Response())->setCode(404);
152
    }
153
154
    /**
155
     * Create user.
156
     */
157
    public function post(string $username, ?string $password = null, ?int $soft_quota = null, ?int $hard_quota = null, ?string $avatar = null, ?string $mail = null, ?bool $admin = false, ?string $namespace = null, ?string $locale = null): Response
158
    {
159
        if (!$this->user->isAdmin()) {
160
            throw new Exception\NotAdmin('submitted parameters require admin privileges');
161
        }
162
163
        $attributes = compact('password', 'soft_quota', 'hard_quota', 'avatar', 'mail', 'admin', 'namespace', 'locale');
164
        $attributes = array_filter($attributes, function ($attribute) {return !is_null($attribute); });
165
166
        if (isset($attributes['avatar'])) {
167
            $attributes['avatar'] = new Binary(base64_decode($attributes['avatar']), Binary::TYPE_GENERIC);
168
        }
169
170
        $id = $this->server->addUser($username, $attributes);
171
        $result = $this->decorator->decorate($this->server->getUserById($id));
172
173
        return (new Response())->setBody($result)->setCode(201);
174
    }
175
176
    /**
177
     * Change attributes.
178
     */
179
    public function patch(string $id, ?string $username = null, ?string $password = null, ?int $soft_quota = null, ?int $hard_quota = null, ?string $avatar = null, ?string $mail = null, ?bool $admin = null, ?string $namespace = null, ?string $locale = null, ?bool $multi_factor_auth = null): Response
180
    {
181
        $attributes = compact('username', 'password', 'soft_quota', 'hard_quota', 'avatar', 'mail', 'admin', 'namespace', 'locale', 'multi_factor_auth');
182
        $attributes = array_filter($attributes, function ($attribute) {return !is_null($attribute); });
183
184
        if (isset($attributes['avatar'])) {
185
            $attributes['avatar'] = new Binary(base64_decode($attributes['avatar']), Binary::TYPE_GENERIC);
186
        }
187
188
        $user = $this->_getUser($id);
189
        $user->setAttributes($attributes);
190
        $result = $this->decorator->decorate($user);
191
192
        return (new Response())->setCode(200)->setBody($result);
193
    }
194
195
    /**
196
     * Delete user.
197
     */
198
    public function delete(string $id, bool $force = false): Response
199
    {
200
        $user = $this->_getUser($id);
201
202
        if ($user->getId() === $this->user->getId()) {
203
            throw new Exception\InvalidArgument(
204
                'can not delete yourself',
205
                Exception\InvalidArgument::CAN_NOT_DELETE_OWN_ACCOUNT
206
            );
207
        }
208
209
        $user->delete($force);
210
211
        return (new Response())->setCode(204);
212
    }
213
214
    /**
215
     * Enable user account.
216
     */
217
    public function postUndelete(string $id): Response
218
    {
219
        $this->_getUser($id)->undelete();
220
221
        return (new Response())->setCode(204);
222
    }
223
}
224