FloKnapp /
faulancer
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Faulancer\Service; |
||
| 4 | |||
| 5 | use Faulancer\Controller\Controller; |
||
| 6 | use Faulancer\Exception\DbException; |
||
| 7 | use Faulancer\Exception\InvalidArgumentException; |
||
| 8 | use Faulancer\ORM\User\Entity; |
||
| 9 | use Faulancer\Security\Crypt; |
||
| 10 | use Faulancer\ServiceLocator\ServiceInterface; |
||
| 11 | |||
| 12 | /** |
||
| 13 | * Class AuthenticatorService | AuthenticatorService.php |
||
| 14 | * |
||
| 15 | * @package Faulancer\Service |
||
| 16 | * @author Florian Knapp <[email protected]> |
||
| 17 | */ |
||
| 18 | class AuthenticatorService implements ServiceInterface |
||
| 19 | { |
||
| 20 | |||
| 21 | /** @var Controller */ |
||
| 22 | protected $controller; |
||
| 23 | |||
| 24 | /** @var DbService */ |
||
| 25 | protected $orm; |
||
| 26 | |||
| 27 | /** @var Config */ |
||
| 28 | protected $config; |
||
| 29 | |||
| 30 | /** @var string */ |
||
| 31 | protected $redirectAfterAuth; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Authenticator constructor. |
||
| 35 | * |
||
| 36 | * @param Controller $controller |
||
| 37 | * @param Config $config |
||
| 38 | */ |
||
| 39 | public function __construct(Controller $controller, Config $config) |
||
| 40 | { |
||
| 41 | $this->controller = $controller; |
||
| 42 | $this->config = $config; |
||
| 43 | } |
||
| 44 | |||
| 45 | /** |
||
| 46 | * Login user with given entity |
||
| 47 | * |
||
| 48 | * @param Entity $user |
||
| 49 | * @param bool $shouldBeActive |
||
| 50 | * @param string $redirectUrl |
||
| 51 | * |
||
| 52 | * @return bool |
||
| 53 | */ |
||
| 54 | public function loginUser(Entity $user, $shouldBeActive = true, $redirectUrl = '') |
||
| 55 | { |
||
| 56 | /** @var Entity $userData */ |
||
| 57 | $userData = $this->controller |
||
|
0 ignored issues
–
show
|
|||
| 58 | ->getDb() |
||
| 59 | ->fetch(get_class($user)) |
||
| 60 | ->where('login', '=', $user->login) |
||
| 61 | ->orWhere('email', '=', $user->login) |
||
| 62 | ->one(); |
||
| 63 | |||
| 64 | if (empty($userData)) { |
||
| 65 | $this->controller->setFlashMessage('error.login', 'invalid_username_or_password'); |
||
| 66 | return $this->redirectToAuthentication(); |
||
| 67 | } |
||
| 68 | |||
| 69 | if ($shouldBeActive && $userData->active !== 1) { |
||
|
0 ignored issues
–
show
The property
active does not exist on object<Faulancer\ORM\User\Entity>. Since you implemented __get, maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. Loading history...
|
|||
| 70 | $this->controller->setFlashMessage('error.active', 'user_is_not_activated'); |
||
| 71 | return $this->redirectToAuthentication(); |
||
| 72 | } |
||
| 73 | |||
| 74 | $passOk = Crypt::verifyPassword($user->password, $userData->password); |
||
| 75 | |||
| 76 | if ($passOk && $userData instanceof Entity) { |
||
| 77 | |||
| 78 | $this->saveUserInSession($userData); |
||
| 79 | |||
| 80 | if ($redirectUrl) { |
||
| 81 | return $this->controller->redirect($redirectUrl); |
||
| 82 | } |
||
| 83 | |||
| 84 | if ($userData->roles[0]->roleName === 'registered') { |
||
| 85 | return $this->controller->redirect($this->controller->route('user')); |
||
| 86 | } else { |
||
| 87 | return $this->controller->redirect($this->controller->route('admin')); |
||
| 88 | } |
||
| 89 | |||
| 90 | } |
||
| 91 | |||
| 92 | $this->controller->setFlashMessage('error.login', 'invalid_username_or_password'); |
||
| 93 | |||
| 94 | return $this->redirectToAuthentication(); |
||
| 95 | } |
||
| 96 | |||
| 97 | /** |
||
| 98 | * @return bool |
||
| 99 | */ |
||
| 100 | public function redirectToAuthentication() |
||
| 101 | { |
||
| 102 | /** @var Config $config */ |
||
| 103 | $config = $this->controller->getServiceLocator()->get(Config::class); |
||
| 104 | $authUrl = $config->get('auth:authUrl'); |
||
| 105 | |||
| 106 | return $this->controller->redirect($authUrl); |
||
| 107 | } |
||
| 108 | |||
| 109 | /** |
||
| 110 | * @param array $roles |
||
| 111 | * @return bool |
||
| 112 | */ |
||
| 113 | public function isPermitted(array $roles): bool |
||
| 114 | { |
||
| 115 | /** @var Entity $user */ |
||
| 116 | $user = $this->getUserFromSession(); |
||
| 117 | |||
| 118 | if (!$user instanceof Entity) { |
||
| 119 | return false; |
||
| 120 | } |
||
| 121 | |||
| 122 | foreach ($user->roles as $userRole) { |
||
| 123 | |||
| 124 | if (in_array($userRole->roleName, $roles, true)) { |
||
| 125 | return true; |
||
| 126 | } |
||
| 127 | |||
| 128 | } |
||
| 129 | |||
| 130 | return false; |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * @param Entity $user |
||
| 135 | * @codeCoverageIgnore |
||
| 136 | */ |
||
| 137 | public function saveUserInSession(Entity $user) |
||
| 138 | { |
||
| 139 | $this->controller->getSessionManager()->set('user', $user->id); |
||
|
0 ignored issues
–
show
The method
set does only exist in Faulancer\Session\SessionManager, but not in Faulancer\ServiceLocator\ServiceInterface.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 140 | } |
||
| 141 | |||
| 142 | /** |
||
| 143 | * @param string $entity |
||
| 144 | * @return Entity * |
||
| 145 | * @codeCoverageIgnore |
||
| 146 | */ |
||
| 147 | public function getUserFromSession(string $entity = '') |
||
| 148 | { |
||
| 149 | $id = $this->controller->getSessionManager()->get('user'); |
||
|
0 ignored issues
–
show
The method
get does only exist in Faulancer\Session\SessionManager, but not in Faulancer\ServiceLocator\ServiceInterface.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 150 | |||
| 151 | if (empty($id)) { |
||
| 152 | return null; |
||
| 153 | } |
||
| 154 | |||
| 155 | /** @var Entity $user */ |
||
| 156 | if (!empty($entity)) { |
||
| 157 | $user = $this->controller->getDb()->fetch($entity, $id); |
||
|
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Faulancer\ServiceLocator\ServiceInterface as the method fetch() does only exist in the following implementations of said interface: Faulancer\Service\DbService.
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
| 158 | } else { |
||
| 159 | $user = $this->controller->getDb()->fetch(Entity::class, $id); |
||
|
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Faulancer\ServiceLocator\ServiceInterface as the method fetch() does only exist in the following implementations of said interface: Faulancer\Service\DbService.
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
| 160 | } |
||
| 161 | |||
| 162 | return $user; |
||
| 163 | } |
||
| 164 | |||
| 165 | } |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: