Completed
Push — develop ( 027f5e...8e896a )
by Neomerx
02:11
created

are.php$0   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
wmc 11
lcom 2
cbo 0
dl 0
loc 106
rs 10
c 0
b 0
f 0
1
<?php namespace Limoncello\Application\Commands;
2
3
/**
4
 * Copyright 2015-2018 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Closure;
20
use Limoncello\Contracts\Authentication\AccountManagerInterface;
21
use Limoncello\Contracts\Commands\IoInterface;
22
use Limoncello\Contracts\Commands\MiddlewareInterface;
23
use Limoncello\Contracts\Passport\PassportAccountInterface;
24
use Limoncello\Contracts\Settings\Packages\CommandSettingsInterface;
25
use Limoncello\Contracts\Settings\SettingsProviderInterface;
26
use Psr\Container\ContainerInterface;
27
28
/**
29
 * @package Limoncello\Application
30
 */
31
abstract class BaseImpersonationMiddleware implements MiddlewareInterface
32
{
33
    /**
34
     * @param ContainerInterface $container
35
     *
36
     * @return Closure
37
     */
38
    abstract protected static function createReadScopesClosure(ContainerInterface $container): Closure;
39
40
    /** Middleware handler */
41
    const CALLABLE_HANDLER = [self::class, self::MIDDLEWARE_METHOD_NAME];
42
43
    /**
44
     * @inheritdoc
45
     */
46
    public static function handle(
47
        IoInterface $inOut,
48
        Closure $next,
49
        ContainerInterface $container
50
    ): void {
51
        /** @var SettingsProviderInterface $provider */
52
        $provider       = $container->get(SettingsProviderInterface::class);
53
        $settings       = $provider->get(CommandSettingsInterface::class);
54
        $userIdentity   = $settings[CommandSettingsInterface::KEY_IMPERSONATE_AS_USER_IDENTITY] ?? null;
55
        $userProperties = $settings[CommandSettingsInterface::KEY_IMPERSONATE_WITH_USER_PROPERTIES] ?? [];
56
57
        /** @var AccountManagerInterface $manager */
58
        $manager = $container->get(AccountManagerInterface::class);
59
        $manager->setAccount(
60
            static::createCliPassport($userIdentity, static::createReadScopesClosure($container), $userProperties)
61
        );
62
63
        call_user_func($next, $inOut);
64
    }
65
66
    /**
67
     * @param int|string $userIdentity
68
     * @param Closure    $readUserScopes
69
     * @param array      $properties
70
     *
71
     * @return PassportAccountInterface
72
     */
73
    protected static function createCliPassport(
74
        $userIdentity,
75
        Closure $readUserScopes,
76
        array $properties
77
    ): PassportAccountInterface {
78
        return new class ($userIdentity, $readUserScopes, $properties) implements PassportAccountInterface
79
        {
80
            /**
81
             * @var array
82
             */
83
            private $properties;
84
85
            /**
86
             * @var int
87
             */
88
            private $userIdentity;
89
90
            /**
91
             * @var Closure
92
             */
93
            private $readUserScopes;
94
95
            /**
96
             * @param int|string $userIdentity
97
             * @param Closure    $readUserScopes
98
             * @param array      $properties
99
             */
100
            public function __construct($userIdentity, Closure $readUserScopes, array $properties)
101
            {
102
                assert (is_int($userIdentity) === true || is_string($userIdentity) === true);
103
104
                $this->userIdentity   = $userIdentity;
0 ignored issues
show
Documentation Bug introduced by
It seems like $userIdentity can also be of type string. However, the property $userIdentity is declared as type integer. 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...
105
                $this->properties     = $properties;
106
                $this->readUserScopes = $readUserScopes;
107
            }
108
109
            /**
110
             * @inheritdoc
111
             */
112
            public function hasProperty($key): bool
113
            {
114
                return array_key_exists($key, $this->properties);
115
            }
116
117
            /**
118
             * @inheritdoc
119
             */
120
            public function getProperty($key)
121
            {
122
                return $this->properties[$key];
123
            }
124
125
            /**
126
             * @inheritdoc
127
             */
128
            public function hasUserIdentity(): bool
129
            {
130
                return true;
131
            }
132
133
            /**
134
             * @inheritdoc
135
             */
136
            public function getUserIdentity()
137
            {
138
                return $this->userIdentity;
139
            }
140
141
            /**
142
             * @inheritdoc
143
             */
144
            public function hasClientIdentity(): bool
145
            {
146
                return false;
147
            }
148
149
            /**
150
             * @inheritdoc
151
             */
152
            public function getClientIdentity()
153
            {
154
                return null;
155
            }
156
157
            /**
158
             * @inheritdoc
159
             */
160
            public function hasScope(string $scope): bool
161
            {
162
                // we typically do just one call during a session so it's fine to work with unsorted data.
163
                return in_array($scope, $this->getScopes());
164
            }
165
166
            /**
167
             * @inheritdoc
168
             */
169
            public function hasScopes(): bool
170
            {
171
                return true;
172
            }
173
174
            /**
175
             * @inheritdoc
176
             */
177
            public function getScopes(): array
178
            {
179
                $scopes = call_user_func($this->readUserScopes, $this->getUserIdentity());
180
181
                return $scopes;
182
            }
183
        };
184
    }
185
}
186