diff --git a/application/Espo/Core/Api/Auth.php b/application/Espo/Core/Api/Auth.php index 950ce8a581..88e06d635e 100644 --- a/application/Espo/Core/Api/Auth.php +++ b/application/Espo/Core/Api/Auth.php @@ -34,14 +34,13 @@ use Espo\Core\Exceptions\{ ServiceUnavailable, }; -use Espo\Core\Authentication\{ - Authentication, - Result, -}; use Espo\Core\{ Api\Request, Api\Response, + Authentication\Authentication, + Authentication\Result, + Utils\Log, }; use Exception; @@ -52,30 +51,24 @@ use Exception; */ class Auth { + protected $log; + protected $authentication; protected $authRequired; + + protected $isEntryPoint; - protected $isEntryPoint = false; - - public function __construct(Authentication $authentication, bool $authRequired = true) - { + public function __construct( + Log $log, + Authentication $authentication, + bool $authRequired = true, + bool $isEntryPoint = false + ) { + $this->log = $log; $this->authentication = $authentication; $this->authRequired = $authRequired; - } - - public static function createForEntryPoint(Authentication $authentication, bool $authRequired = true) : self - { - $instance = new Auth($authentication, $authRequired); - - $instance->isEntryPoint = true; - - return $instance; - } - - public static function createBuilder() : AuthBuilder - { - return new AuthBuilder(); + $this->isEntryPoint = $isEntryPoint; } public function process(Request $request, Response $response) : AuthResult @@ -213,14 +206,14 @@ class Auth $response->setStatus($e->getCode()); - $GLOBALS['log']->notice("Auth: " . $e->getMessage()); + $this->log->notice("Auth: " . $e->getMessage()); return; } $response->setStatus(500); - $GLOBALS['log']->error("Auth: " . $e->getMessage()); + $this->log->error("Auth: " . $e->getMessage()); } protected function handleUnauthorized(Response $response, bool $showDialog) diff --git a/application/Espo/Core/Api/AuthBuilder.php b/application/Espo/Core/Api/AuthBuilder.php index 606b1fde16..e8c18823f4 100644 --- a/application/Espo/Core/Api/AuthBuilder.php +++ b/application/Espo/Core/Api/AuthBuilder.php @@ -29,10 +29,10 @@ namespace Espo\Core\Api; -use Espo\Core\Exceptions\Error; - -use Espo\Core\Authentication\{ - Authentication, +use Espo\Core\{ + Exceptions\Error, + Authentication\Authentication, + Utils\Log, }; /** @@ -46,6 +46,13 @@ class AuthBuilder private $authentication = null; + private $log; + + public function __construct(Log $log) + { + $this->log = $log; + } + public function setAuthentication(Authentication $authentication) : self { $this->authentication = $authentication; @@ -73,10 +80,6 @@ class AuthBuilder throw new Error("Authentication is not set."); } - if ($this->isEntryPoint) { - return Auth::createForEntryPoint($this->authentication, $this->authRequired); - } - - return new Auth($this->authentication, $this->authRequired); + return new Auth($this->log, $this->authentication, $this->authRequired, $this->isEntryPoint); } } diff --git a/application/Espo/Core/Api/AuthBuilderFactory.php b/application/Espo/Core/Api/AuthBuilderFactory.php new file mode 100644 index 0000000000..21d433e336 --- /dev/null +++ b/application/Espo/Core/Api/AuthBuilderFactory.php @@ -0,0 +1,49 @@ +log = $log; + } + + public function create() : AuthBuilder + { + return new AuthBuilder($this->log); + } +} diff --git a/application/Espo/Core/ApplicationRunners/Api.php b/application/Espo/Core/ApplicationRunners/Api.php index 82436d2f0d..a4fee56fca 100644 --- a/application/Espo/Core/ApplicationRunners/Api.php +++ b/application/Espo/Core/ApplicationRunners/Api.php @@ -33,7 +33,7 @@ use Espo\Core\{ InjectableFactory, ApplicationUser, Authentication\Authentication, - Api\Auth as ApiAuth, + Api\AuthBuilderFactory, Api\ErrorOutput as ApiErrorOutput, Api\RequestWrapper, Api\ResponseWrapper, @@ -63,14 +63,20 @@ class Api implements ApplicationRunner protected $injectableFactory; protected $applicationUser; protected $routeUtil; + protected $authBuilderFactory; protected $log; public function __construct( - InjectableFactory $injectableFactory, ApplicationUser $applicationUser, Route $routeUtil, Log $log + InjectableFactory $injectableFactory, + ApplicationUser $applicationUser, + Route $routeUtil, + AuthBuilderFactory $authBuilderFactory, + Log $log ) { $this->injectableFactory = $injectableFactory; $this->applicationUser = $applicationUser; $this->routeUtil = $routeUtil; + $this->authBuilderFactory = $authBuilderFactory; $this->log = $log; } @@ -161,7 +167,8 @@ class Api implements ApplicationRunner $authentication = $this->injectableFactory->create(Authentication::class); - $apiAuth = ApiAuth::createBuilder() + $apiAuth = $this->authBuilderFactory + ->create() ->setAuthentication($authentication) ->setAuthRequired($authRequired) ->build(); diff --git a/application/Espo/Core/ApplicationRunners/EntryPoint.php b/application/Espo/Core/ApplicationRunners/EntryPoint.php index 6c5266a3a8..dac1ebc19d 100644 --- a/application/Espo/Core/ApplicationRunners/EntryPoint.php +++ b/application/Espo/Core/ApplicationRunners/EntryPoint.php @@ -39,7 +39,7 @@ use Espo\Core\{ Utils\Route, Utils\ClientManager, Authentication\Authentication, - Api\Auth as ApiAuth, + Api\AuthBuilderFactory, Api\ErrorOutput as ApiErrorOutput, Api\RequestWrapper, Api\ResponseWrapper, @@ -68,6 +68,7 @@ class EntryPoint implements ApplicationRunner protected $clientManager; protected $applicationUser; protected $authTokenManager; + protected $authBuilderFactory; public function __construct( InjectableFactory $injectableFactory, @@ -76,6 +77,7 @@ class EntryPoint implements ApplicationRunner ClientManager $clientManager, ApplicationUser $applicationUser, AuthTokenManager $authTokenManager, + AuthBuilderFactory $authBuilderFactory, ?StdClass $params = null ) { $this->injectableFactory = $injectableFactory; @@ -84,6 +86,7 @@ class EntryPoint implements ApplicationRunner $this->clientManager = $clientManager; $this->applicationUser = $applicationUser; $this->authTokenManager = $authTokenManager; + $this->authBuilderFactory = $authBuilderFactory; $this->params = $params ?? (object) []; } @@ -140,7 +143,8 @@ class EntryPoint implements ApplicationRunner 'allowAnyAccess' => $authNotStrict, ]); - $apiAuth = ApiAuth::createBuilder() + $apiAuth = $this->authBuilderFactory + ->create() ->setAuthentication($authentication) ->setAuthRequired($authRequired) ->forEntryPoint() diff --git a/application/Espo/Core/Authentication/Authentication.php b/application/Espo/Core/Authentication/Authentication.php index 0fd0eea8fc..9e4aca2fca 100644 --- a/application/Espo/Core/Authentication/Authentication.php +++ b/application/Espo/Core/Authentication/Authentication.php @@ -56,6 +56,7 @@ use Espo\Core\{ Utils\Metadata, ORM\EntityManagerProxy, Api\Request, + Utils\Log, }; use DateTime; @@ -80,6 +81,7 @@ class Authentication protected $entityManager; protected $authLoginFactory; protected $auth2FAFactory; + protected $log; public function __construct( ApplicationUser $applicationUser, @@ -90,6 +92,7 @@ class Authentication LoginFactory $authLoginFactory, TwoFAFactory $auth2FAFactory, AuthTokenManager $authTokenManager, + Log $log, bool $allowAnyAccess = false ) { $this->allowAnyAccess = $allowAnyAccess; @@ -102,6 +105,7 @@ class Authentication $this->authLoginFactory = $authLoginFactory; $this->auth2FAFactory = $auth2FAFactory; $this->authTokenManager = $authTokenManager; + $this->log = $log; } protected function getDefaultAuthenticationMethod() @@ -139,7 +143,7 @@ class Authentication if ($authenticationMethod) { if (!$this->metadata->get(['authenticationMethods', $authenticationMethod, 'api'])) { - $GLOBALS['log']->warning( + $this->log->warning( "AUTH: Trying to use not allowed authentication method '{$authenticationMethod}'." ); @@ -179,13 +183,17 @@ class Authentication if ($authToken && $authToken->isActive()) { if (!$this->allowAnyAccess) { if ($this->isPortal() && $authToken->getPortalId() !== $this->getPortal()->id) { - $GLOBALS['log']->info("AUTH: Trying to login to portal with a token not related to portal."); + $this->log->info( + "AUTH: Trying to login to portal with a token not related to portal." + ); return Result::fail('Denied'); } if (!$this->isPortal() && $authToken->getPortalId()) { - $GLOBALS['log']->info("AUTH: Trying to login to crm with a token related to portal."); + $this->log->info( + "AUTH: Trying to login to crm with a token related to portal." + ); return Result::fail('Denied'); } @@ -206,7 +214,9 @@ class Authentication if ($isByTokenOnly && !$authToken) { if ($username) { - $GLOBALS['log']->info("AUTH: Trying to login as user '{$username}' by token but token is not found."); + $this->log->info( + "AUTH: Trying to login as user '{$username}' by token but token is not found." + ); } return Result::fail('Token not found'); @@ -304,7 +314,7 @@ class Authentication protected function processUserCheck(User $user, ?AuthLogRecord $authLogRecord) : bool { if (!$user->isActive()) { - $GLOBALS['log']->info( + $this->log->info( "AUTH: Trying to login as user '".$user->get('userName')."' which is not active." ); @@ -314,7 +324,7 @@ class Authentication } if (!$user->isAdmin() && !$this->isPortal() && $user->isPortal()) { - $GLOBALS['log']->info( + $this->log->info( "AUTH: Trying to login to crm as a portal user '".$user->get('userName')."'." ); @@ -324,7 +334,7 @@ class Authentication } if ($this->isPortal() && !$user->isPortal()) { - $GLOBALS['log']->info( + $this->log->info( "AUTH: Trying to login to portal as user '".$user->get('userName')."' which is not portal user." ); @@ -339,7 +349,7 @@ class Authentication ->isRelated($this->getPortal(), 'users', $user); if (!$isPortalRelatedToUser) { - $GLOBALS['log']->info( + $this->log->info( "AUTH: Trying to login to portal as user '".$user->get('userName')."' ". "which is portal user but does not belongs to portal." ); @@ -441,7 +451,7 @@ class Authentication } if ($failAttemptCount > $maxFailedAttempts) { - $GLOBALS['log']->warning( + $this->log->warning( "AUTH: Max failed login attempts exceeded for IP '{$ip}'." );