refactoring

This commit is contained in:
Yuri Kuznetsov
2021-08-30 12:00:51 +03:00
parent 134cd53f45
commit 84830d6aef
6 changed files with 214 additions and 74 deletions
+17 -35
View File
@@ -35,6 +35,7 @@ use Espo\Core\Exceptions\ServiceUnavailable;
use Espo\Core\Api\Request;
use Espo\Core\Api\Response;
use Espo\Core\Authentication\Authentication;
use Espo\Core\Authentication\AuthenticationData;
use Espo\Core\Authentication\Result;
use Espo\Core\Utils\Log;
@@ -77,15 +78,18 @@ class Auth
list($username, $password) = $this->obtainUsernamePasswordFromRequest($request);
}
$authenticationData = AuthenticationData::create()
->withUsername($username)
->withPassword($password)
->withMethod($authenticationMethod);
$hasAuthData = (bool) ($username || $authenticationMethod);
if (!$this->authRequired && !$this->isEntryPoint && $hasAuthData) {
$authResult = $this->processAuthNotRequired(
$username,
$password,
$authenticationData,
$request,
$response,
$authenticationMethod
$response
);
if ($authResult) {
@@ -98,13 +102,7 @@ class Auth
}
if ($hasAuthData) {
return $this->processWithAuthData(
$username,
$password,
$request,
$response,
$authenticationMethod
);
return $this->processWithAuthData($authenticationData, $request, $response);
}
$showDialog = $this->isEntryPoint;
@@ -118,22 +116,14 @@ class Auth
return AuthResult::createNotResolved();
}
protected function processAuthNotRequired(
string $username,
?string $password,
private function processAuthNotRequired(
AuthenticationData $data,
Request $request,
Response $response,
?string $authenticationMethod
Response $response
): ?AuthResult {
try {
$result = $this->authentication->login(
$username,
$password,
$request,
$response,
$authenticationMethod
);
$result = $this->authentication->login($data, $request, $response);
}
catch (Exception $e) {
$this->handleException($response, $e);
@@ -148,24 +138,16 @@ class Auth
return null;
}
protected function processWithAuthData(
?string $username,
?string $password,
private function processWithAuthData(
AuthenticationData $data,
Request $request,
Response $response,
?string $authenticationMethod
Response $response
): AuthResult {
$showDialog = $this->isEntryPoint;
try {
$result = $this->authentication->login(
$username,
$password,
$request,
$response,
$authenticationMethod
);
$result = $this->authentication->login($data, $request, $response);
}
catch (Exception $e) {
$this->handleException($response, $e);
@@ -108,38 +108,19 @@ class Authentication
$this->log = $log;
}
protected function setPortal(Portal $portal)
{
$this->portal = $portal;
}
protected function isPortal(): bool
{
return (bool) $this->portal || $this->applicationState->isPortal();
}
protected function getPortal(): Portal
{
if ($this->portal) {
return $this->portal;
}
return $this->applicationState->getPortal();
}
/**
* Process logging in.
*
* Warning: This method can change the state of the object (by setting the `portal` prop.).
*
* @throws Forbidden
* @throws ServiceUnavailable
*/
public function login(
?string $username,
?string $password,
Request $request,
Response $response,
?string $authenticationMethod = null
): Result {
public function login(AuthenticationData $data, Request $request, Response $response): Result
{
$username = $data->getUsername();
$password = $data->getPassword();
$authenticationMethod = $data->getMethod();
if (
$authenticationMethod &&
@@ -161,6 +142,12 @@ class Authentication
$authToken = null;
$authTokenIsFound = false;
if (!$authenticationMethod && $password === null) {
$this->log->error("AUTH: Trying to login w/o password.");
return Result::fail('No password');
}
if (!$authenticationMethod) {
$authToken = $this->authTokenManager->get($password);
}
@@ -239,7 +226,7 @@ class Authentication
}
if ($this->isPortal()) {
$user->set('portalId', $this->getPortal()->id);
$user->set('portalId', $this->getPortal()->getId());
}
if (!$this->isPortal()) {
@@ -300,6 +287,25 @@ class Authentication
return $result;
}
private function setPortal(Portal $portal): void
{
$this->portal = $portal;
}
private function isPortal(): bool
{
return (bool) $this->portal || $this->applicationState->isPortal();
}
private function getPortal(): Portal
{
if ($this->portal) {
return $this->portal;
}
return $this->applicationState->getPortal();
}
private function processAuthTokenCheck(AuthToken $authToken): bool
{
if ($this->allowAnyAccess && $authToken->getPortalId() && !$this->isPortal()) {
@@ -314,7 +320,7 @@ class Authentication
return true;
}
if ($this->isPortal() && $authToken->getPortalId() !== $this->getPortal()->id) {
if ($this->isPortal() && $authToken->getPortalId() !== $this->getPortal()->getId()) {
$this->log->info(
"AUTH: Trying to login to portal with a token not related to portal."
);
@@ -490,7 +496,7 @@ class Authentication
'hash' => $user->get('password'),
'ipAddress' => $request->getServerParam('REMOTE_ADDR'),
'userId' => $user->id,
'portalId' => $this->isPortal() ? $this->getPortal()->id : null,
'portalId' => $this->isPortal() ? $this->getPortal()->getId() : null,
'createSecret' => $createSecret,
];
@@ -547,7 +553,7 @@ class Authentication
return true;
}
protected function createAuthLogRecord(
private function createAuthLogRecord(
?string $username,
?User $user,
Request $request,
@@ -579,7 +585,7 @@ class Authentication
]);
if ($this->isPortal()) {
$authLogRecord->set('portalId', $this->getPortal()->id);
$authLogRecord->set('portalId', $this->getPortal()->getId());
}
if ($user) {
@@ -0,0 +1,93 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Authentication;
class AuthenticationData
{
private $username;
private $password;
private $method;
public function __construct(
?string $username = null,
?string $password = null,
?string $method = null
) {
$this->username = $username;
$this->password = $password;
$this->method = $method;
}
public static function create(): self
{
return new self();
}
public function getUsername(): ?string
{
return $this->username;
}
public function getPassword(): ?string
{
return $this->password;
}
public function getMethod(): ?string
{
return $this->method;
}
public function withUsername(?string $username): self
{
$obj = clone $this;
$obj->username = $username;
return $obj;
}
public function withPassword(?string $password): self
{
$obj = clone $this;
$obj->password = $password;
return $obj;
}
public function withMethod(?string $method): self
{
$obj = clone $this;
$obj->method = $method;
return $obj;
}
}
@@ -33,7 +33,7 @@ use Espo\Core\InjectableFactory;
class AuthenticationFactory
{
protected $injectableFactory;
private $injectableFactory;
public function __construct(InjectableFactory $injectableFactory)
{
+7 -7
View File
@@ -30,6 +30,7 @@
namespace tests\integration\Core;
use Espo\Core\Authentication\Authentication;
use Espo\Core\Authentication\AuthenticationData;
use Espo\Core\Application;
use Espo\Core\Portal\Application as PortalApplication;
@@ -212,13 +213,12 @@ class Tester
if (isset($this->userName) || $this->authenticationMethod) {
$this->password = isset($this->password) ? $this->password : $this->defaultUserPassword;
$auth->login(
$this->userName,
$this->password,
$request,
$response,
$this->authenticationMethod
);
$authenticationData = AuthenticationData::create()
->withUsername($this->userName)
->withPassword($this->password)
->withMethod($this->authenticationMethod);
$auth->login($authenticationData, $request, $response);
}
else {
$this->application->setupSystemUser();
@@ -0,0 +1,59 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Authentication;
use Espo\Core\Authentication\AuthenticationData;
class AuthenticationDataTest extends \PHPUnit\Framework\TestCase
{
public function testCreate1(): void
{
$data = AuthenticationData::create()
->withUsername('u')
->withPassword('p')
->withMethod(null);
$this->assertEquals('u', $data->getUsername());
$this->assertEquals('p', $data->getPassword());
$this->assertNull($data->getMethod());
}
public function testCreate2(): void
{
$data = AuthenticationData::create()
->withUsername(null)
->withPassword(null)
->withMethod('m');
$this->assertNull($data->getUsername());
$this->assertNull($data->getPassword());
$this->assertEquals('m', $data->getMethod());
}
}