mirror of
https://github.com/nuxsmin/sysPass.git
synced 2026-03-04 23:54:08 +01:00
chore(tests): UT for UserMasterPass service
Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
@@ -43,7 +43,7 @@ use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\Core\PhpExtensionCheckerService;
|
||||
use SP\Domain\Core\UI\ThemeInterface;
|
||||
use SP\Domain\Http\RequestInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Modules\Web\Controllers\Helpers\LayoutHelper;
|
||||
use SP\Modules\Web\Controllers\Traits\WebControllerTrait;
|
||||
use SP\Mvc\Controller\WebControllerHelper;
|
||||
@@ -71,9 +71,9 @@ abstract class ControllerBase
|
||||
protected ConfigDataInterface $configData;
|
||||
protected RequestInterface $request;
|
||||
protected PhpExtensionCheckerService $extensionChecker;
|
||||
protected TemplateInterface $view;
|
||||
protected ?UserLoginResponse $userData = null;
|
||||
protected ?ProfileData $userProfileData = null;
|
||||
protected TemplateInterface $view;
|
||||
protected ?UserDataDto $userData = null;
|
||||
protected ?ProfileData $userProfileData = null;
|
||||
protected bool $isAjax;
|
||||
protected LayoutHelper $layoutHelper;
|
||||
protected string $actionName;
|
||||
|
||||
@@ -28,9 +28,9 @@ use Exception;
|
||||
use JsonException;
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Services\UserService;
|
||||
use SP\Http\JsonMessage;
|
||||
use SP\Modules\Web\Controllers\SimpleControllerBase;
|
||||
@@ -87,11 +87,11 @@ final class SaveController extends SimpleControllerBase
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
*
|
||||
* @return UserPreferences
|
||||
*/
|
||||
private function getUserPreferencesData(UserLoginResponse $userData): UserPreferences
|
||||
private function getUserPreferencesData(UserDataDto $userData): UserPreferences
|
||||
{
|
||||
$userPreferencesData = clone $userData->getPreferences();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -29,7 +29,7 @@ use SP\Domain\Account\Dtos\AccountCacheDto;
|
||||
use SP\Domain\Account\Dtos\AccountSearchFilterDto;
|
||||
use SP\Domain\Core\Context\SessionContextInterface;
|
||||
use SP\Domain\Core\Crypt\VaultInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
|
||||
use function SP\__u;
|
||||
use function SP\getLastCaller;
|
||||
@@ -145,9 +145,9 @@ class SessionContext extends ContextBase implements SessionContextInterface
|
||||
/**
|
||||
* Establece los datos del usuario en la sesión.
|
||||
*/
|
||||
public function setUserData(?UserLoginResponse $userLoginResponse = null): void
|
||||
public function setUserData(?UserDataDto $userDataDto = null): void
|
||||
{
|
||||
$this->setContextKey('userData', $userLoginResponse);
|
||||
$this->setContextKey('userData', $userDataDto);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,9 +193,9 @@ class SessionContext extends ContextBase implements SessionContextInterface
|
||||
/**
|
||||
* Devuelve los datos del usuario en la sesión.
|
||||
*/
|
||||
public function getUserData(): UserLoginResponse
|
||||
public function getUserData(): UserDataDto
|
||||
{
|
||||
return $this->getContextKey('userData', new UserLoginResponse());
|
||||
return $this->getContextKey('userData', new UserDataDto());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace SP\Core\Context;
|
||||
|
||||
use SP\DataModel\ProfileData;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
|
||||
use function SP\processException;
|
||||
|
||||
@@ -39,9 +39,9 @@ class StatelessContext extends ContextBase
|
||||
/**
|
||||
* Establece los datos del usuario en la sesión.
|
||||
*/
|
||||
public function setUserData(?UserLoginResponse $userLoginResponse = null): void
|
||||
public function setUserData(?UserDataDto $userDataDto = null): void
|
||||
{
|
||||
$this->setContextKey('userData', $userLoginResponse);
|
||||
$this->setContextKey('userData', $userDataDto);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +99,9 @@ class StatelessContext extends ContextBase
|
||||
/**
|
||||
* Devuelve los datos del usuario en la sesión.
|
||||
*/
|
||||
public function getUserData(): UserLoginResponse
|
||||
public function getUserData(): UserDataDto
|
||||
{
|
||||
return $this->getContextKey('userData', new UserLoginResponse());
|
||||
return $this->getContextKey('userData', new UserDataDto());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -96,7 +96,7 @@ use SP\Providers\Auth\AuthTypeEnum;
|
||||
use SP\Providers\Auth\Browser\BrowserAuth;
|
||||
use SP\Providers\Auth\Browser\BrowserAuthInterface;
|
||||
use SP\Providers\Auth\Database\DatabaseAuth;
|
||||
use SP\Providers\Auth\Database\DatabaseAuthInterface;
|
||||
use SP\Providers\Auth\Database\DatabaseAuthService;
|
||||
use SP\Providers\Auth\Ldap\LdapActions;
|
||||
use SP\Providers\Auth\Ldap\LdapAuth;
|
||||
use SP\Providers\Auth\Ldap\LdapBase;
|
||||
@@ -166,7 +166,7 @@ final class CoreDefinitions
|
||||
),
|
||||
ThemeInterface::class => autowire(Theme::class),
|
||||
TemplateInterface::class => autowire(Template::class),
|
||||
DatabaseAuthInterface::class => autowire(DatabaseAuth::class),
|
||||
DatabaseAuthService::class => autowire(DatabaseAuth::class),
|
||||
BrowserAuthInterface::class => autowire(BrowserAuth::class),
|
||||
LdapParams::class => factory([LdapParams::class, 'getFrom']),
|
||||
LdapConnectionInterface::class => autowire(LdapConnection::class),
|
||||
@@ -178,11 +178,11 @@ final class CoreDefinitions
|
||||
),
|
||||
AuthProviderInterface::class => factory(
|
||||
static function (
|
||||
AuthProvider $authProvider,
|
||||
ConfigDataInterface $configData,
|
||||
LdapAuthService $ldapAuth,
|
||||
BrowserAuthInterface $browserAuth,
|
||||
DatabaseAuthInterface $databaseAuth,
|
||||
AuthProvider $authProvider,
|
||||
ConfigDataInterface $configData,
|
||||
LdapAuthService $ldapAuth,
|
||||
BrowserAuthInterface $browserAuth,
|
||||
DatabaseAuthService $databaseAuth,
|
||||
) {
|
||||
if ($configData->isLdapEnabled()) {
|
||||
$authProvider->registerAuth($ldapAuth, AuthTypeEnum::Ldap);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -29,7 +29,7 @@ use SP\Domain\Account\Adapters\AccountPermission;
|
||||
use SP\Domain\Account\Dtos\AccountAclDto;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
|
||||
/**
|
||||
* Class AccountAclService
|
||||
@@ -41,12 +41,12 @@ interface AccountAclService
|
||||
/**
|
||||
* Sets grants which don't need the account's data
|
||||
*
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param ProfileData $profileData
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function getShowPermission(UserLoginResponse $userData, ProfileData $profileData): bool;
|
||||
public static function getShowPermission(UserDataDto $userData, ProfileData $profileData): bool;
|
||||
|
||||
/**
|
||||
* Obtener la ACL de una cuenta
|
||||
|
||||
@@ -56,7 +56,7 @@ use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\ItemPreset\Ports\ItemPresetInterface;
|
||||
use SP\Domain\ItemPreset\Ports\ItemPresetService;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Infrastructure\Database\QueryResult;
|
||||
|
||||
@@ -247,14 +247,14 @@ final class Account extends Service implements AccountService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param ProfileData $userProfile
|
||||
* @param AccountModel $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function userCanChangeOwner(
|
||||
UserLoginResponse $userData,
|
||||
UserDataDto $userData,
|
||||
ProfileData $userProfile,
|
||||
AccountModel $account
|
||||
): bool {
|
||||
@@ -263,14 +263,14 @@ final class Account extends Service implements AccountService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param ProfileData $userProfile
|
||||
* @param AccountModel $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function userCanChangeGroup(
|
||||
UserLoginResponse $userData,
|
||||
UserDataDto $userData,
|
||||
ProfileData $userProfile,
|
||||
AccountModel $account
|
||||
): bool {
|
||||
@@ -335,13 +335,13 @@ final class Account extends Service implements AccountService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param AccountCreateDto $accountCreateDto
|
||||
*
|
||||
* @return AccountCreateDto
|
||||
*/
|
||||
private static function buildWithUserData(
|
||||
UserLoginResponse $userData,
|
||||
UserDataDto $userData,
|
||||
AccountCreateDto $accountCreateDto
|
||||
): AccountCreateDto {
|
||||
return $accountCreateDto->withUserGroupId($userData->getUserGroupId())->withUserId($userData->getId());
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace SP\Domain\Account\Services;
|
||||
|
||||
use SP\Core\Acl\Acl;
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Core\Events\EventMessage;
|
||||
@@ -38,8 +37,8 @@ use SP\Domain\Core\Acl\AclInterface;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Storage\Ports\FileCacheService;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Ports\UserToUserGroupServiceInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Infrastructure\File\FileException;
|
||||
|
||||
use function SP\processException;
|
||||
@@ -56,25 +55,19 @@ final class AccountAcl extends Service implements AccountAclService
|
||||
*/
|
||||
public const ACL_PATH = CACHE_PATH . DIRECTORY_SEPARATOR . 'accountAcl' . DIRECTORY_SEPARATOR;
|
||||
|
||||
private ?AccountAclDto $accountAclDto = null;
|
||||
private ?AccountPermission $accountAcl = null;
|
||||
private Acl $acl;
|
||||
private ?FileCacheService $fileCache;
|
||||
private UserToUserGroupServiceInterface $userToUserGroupService;
|
||||
private UserLoginResponse $userData;
|
||||
private ?AccountAclDto $accountAclDto = null;
|
||||
private ?AccountPermission $accountAcl = null;
|
||||
private UserDataDto $userData;
|
||||
|
||||
public function __construct(
|
||||
Application $application,
|
||||
AclInterface $acl,
|
||||
UserToUserGroupServiceInterface $userGroupService,
|
||||
?FileCacheService $fileCache = null
|
||||
Application $application,
|
||||
private readonly AclInterface $acl,
|
||||
private readonly UserToUserGroupServiceInterface $userToUserGroupService,
|
||||
private readonly ?FileCacheService $fileCache = null
|
||||
) {
|
||||
parent::__construct($application);
|
||||
|
||||
$this->acl = $acl;
|
||||
$this->userToUserGroupService = $userGroupService;
|
||||
$this->userData = $this->context->getUserData();
|
||||
$this->fileCache = $fileCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,12 +123,12 @@ final class AccountAcl extends Service implements AccountAclService
|
||||
/**
|
||||
* Sets grants which don't need the account's data
|
||||
*
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param ProfileData $profileData
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function getShowPermission(UserLoginResponse $userData, ProfileData $profileData): bool
|
||||
public static function getShowPermission(UserDataDto $userData, ProfileData $profileData): bool
|
||||
{
|
||||
return $userData->getIsAdminApp()
|
||||
|| $userData->getIsAdminAcc()
|
||||
|
||||
@@ -31,7 +31,7 @@ use SP\Domain\Account\Ports\AccountFilterBuilder;
|
||||
use SP\Domain\Account\Ports\AccountSearchConstants;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
use SP\Domain\Core\Context\ContextInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
|
||||
/**
|
||||
* Class AccountFilterUser
|
||||
@@ -91,14 +91,14 @@ final class AccountFilter implements AccountFilterBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserLoginResponse $userData
|
||||
* @param UserDataDto $userData
|
||||
* @param bool $useGlobalSearch
|
||||
* @param ProfileData|null $userProfile
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isFilterWithoutGlobalSearch(
|
||||
UserLoginResponse $userData,
|
||||
UserDataDto $userData,
|
||||
bool $useGlobalSearch,
|
||||
?ProfileData $userProfile
|
||||
): bool {
|
||||
|
||||
@@ -46,9 +46,9 @@ use SP\Domain\Core\Exceptions\InvalidClassException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\Security\Dtos\TrackRequest;
|
||||
use SP\Domain\Security\Ports\TrackService;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Ports\UserProfileServiceInterface;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Domain\User\Services\UserService;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Modules\Api\Controllers\Help\HelpInterface;
|
||||
use SP\Util\Filter;
|
||||
@@ -216,7 +216,7 @@ final class Api extends Service implements ApiService
|
||||
*/
|
||||
private function setupUser(): void
|
||||
{
|
||||
$userLoginResponse = UserService::mapUserLoginResponse(
|
||||
$userLoginResponse = new UserDataDto(
|
||||
$this->userService->getById($this->authToken->getUserId())
|
||||
);
|
||||
$userLoginResponse->getIsDisabled() && $this->accessDenied();
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace SP\Domain\Auth\Dtos;
|
||||
*
|
||||
* @package SP\Domain\Auth\Services
|
||||
*/
|
||||
final class LoginResponse
|
||||
final class LoginResponseDto
|
||||
{
|
||||
private int $status;
|
||||
private ?string $redirect;
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -22,20 +22,30 @@
|
||||
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\DataModel;
|
||||
namespace SP\Domain\Auth\Dtos;
|
||||
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
|
||||
/**
|
||||
* Class UserLoginData
|
||||
*
|
||||
* @package SP\DataModel
|
||||
* Class UserLoginDto
|
||||
*/
|
||||
class UserLoginData
|
||||
class UserLoginDto
|
||||
{
|
||||
protected ?string $loginUser = null;
|
||||
protected ?string $loginPass = null;
|
||||
protected ?UserLoginResponse $userLoginResponse = null;
|
||||
protected ?string $loginUser = null;
|
||||
protected ?string $loginPass = null;
|
||||
protected ?UserDataDto $userDataDto = null;
|
||||
|
||||
/**
|
||||
* @param string|null $loginUser
|
||||
* @param string|null $loginPass
|
||||
* @param UserDataDto|null $userDataDto
|
||||
*/
|
||||
public function __construct(?string $loginUser = null, ?string $loginPass = null, ?UserDataDto $userDataDto = null)
|
||||
{
|
||||
$this->loginUser = $loginUser;
|
||||
$this->loginPass = $loginPass;
|
||||
$this->userDataDto = $userDataDto;
|
||||
}
|
||||
|
||||
public function getLoginUser(): ?string
|
||||
{
|
||||
@@ -57,13 +67,13 @@ class UserLoginData
|
||||
$this->loginPass = $loginPass;
|
||||
}
|
||||
|
||||
public function getUserLoginResponse(): ?UserLoginResponse
|
||||
public function getUserDataDto(): ?UserDataDto
|
||||
{
|
||||
return $this->userLoginResponse;
|
||||
return $this->userDataDto;
|
||||
}
|
||||
|
||||
public function setUserLoginResponse(UserLoginResponse $userLoginResponse = null): void
|
||||
public function setUserDataDto(UserDataDto $userDataDto = null): void
|
||||
{
|
||||
$this->userLoginResponse = $userLoginResponse;
|
||||
$this->userDataDto = $userDataDto;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace SP\Domain\Auth\Ports;
|
||||
|
||||
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
||||
use Exception;
|
||||
use SP\Domain\Auth\Dtos\LoginResponse;
|
||||
use SP\Domain\Auth\Dtos\LoginResponseDto;
|
||||
use SP\Domain\Auth\Services\AuthException;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
@@ -42,7 +42,7 @@ interface LoginService
|
||||
/**
|
||||
* Ejecutar las acciones de login
|
||||
*
|
||||
* @return LoginResponse
|
||||
* @return LoginResponseDto
|
||||
* @throws AuthException
|
||||
* @throws SPException
|
||||
* @throws EnvironmentIsBrokenException
|
||||
@@ -54,7 +54,7 @@ interface LoginService
|
||||
* @uses Login::authLdap()
|
||||
*
|
||||
*/
|
||||
public function doLogin(): LoginResponse;
|
||||
public function doLogin(): LoginResponseDto;
|
||||
|
||||
/**
|
||||
* @param string|null $from
|
||||
|
||||
@@ -24,19 +24,21 @@
|
||||
|
||||
namespace SP\Domain\Auth\Services;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
||||
use Exception;
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Core\Events\EventMessage;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\LoginResponse;
|
||||
use SP\DataModel\ProfileData;
|
||||
use SP\Domain\Auth\Dtos\LoginResponseDto;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Auth\Ports\LdapAuthService;
|
||||
use SP\Domain\Auth\Ports\LoginService;
|
||||
use SP\Domain\Common\Services\Service;
|
||||
use SP\Domain\Common\Services\ServiceException;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\CryptException;
|
||||
use SP\Domain\Core\Exceptions\InvalidArgumentException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
@@ -45,13 +47,12 @@ use SP\Domain\Crypt\Ports\TemporaryMasterPassService;
|
||||
use SP\Domain\Http\RequestInterface;
|
||||
use SP\Domain\Security\Dtos\TrackRequest;
|
||||
use SP\Domain\Security\Ports\TrackService;
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
use SP\Domain\User\Ports\UserMasterPassService;
|
||||
use SP\Domain\User\Ports\UserPassRecoverService;
|
||||
use SP\Domain\User\Ports\UserPassServiceInterface;
|
||||
use SP\Domain\User\Ports\UserProfileServiceInterface;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Domain\User\Services\UserLoginRequest;
|
||||
use SP\Domain\User\Services\UserPassService;
|
||||
use SP\Domain\User\Services\UserMasterPassStatus;
|
||||
use SP\Http\Uri;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Providers\Auth\AuthProviderInterface;
|
||||
@@ -61,6 +62,7 @@ use SP\Providers\Auth\Ldap\LdapAuthData;
|
||||
use SP\Providers\Auth\Ldap\LdapCodeEnum;
|
||||
use SP\Util\PasswordUtil;
|
||||
|
||||
use function SP\__;
|
||||
use function SP\__u;
|
||||
|
||||
/**
|
||||
@@ -77,7 +79,7 @@ final class Login extends Service implements LoginService
|
||||
private const STATUS_PASS = 0;
|
||||
private const STATUS_NONE = 100;
|
||||
|
||||
private UserLoginData $userLoginData;
|
||||
private UserLoginDto $userLoginData;
|
||||
private ConfigDataInterface $configData;
|
||||
private TrackRequest $trackRequest;
|
||||
private ?string $from = null;
|
||||
@@ -94,13 +96,13 @@ final class Login extends Service implements LoginService
|
||||
private readonly UserServiceInterface $userService,
|
||||
private readonly UserPassRecoverService $userPassRecoverService,
|
||||
private readonly TemporaryMasterPassService $temporaryMasterPassService,
|
||||
private readonly UserPassServiceInterface $userPassService,
|
||||
private readonly UserMasterPassService $userMasterPassService,
|
||||
private readonly UserProfileServiceInterface $userProfileService
|
||||
) {
|
||||
parent::__construct($application);
|
||||
|
||||
$this->configData = $this->config->getConfigData();
|
||||
$this->userLoginData = new UserLoginData();
|
||||
$this->userLoginData = new UserLoginDto();
|
||||
$this->trackRequest = $this->trackService->buildTrackRequest(__CLASS__);
|
||||
$this->authProvider->initialize();
|
||||
}
|
||||
@@ -108,7 +110,7 @@ final class Login extends Service implements LoginService
|
||||
/**
|
||||
* Ejecutar las acciones de login
|
||||
*
|
||||
* @return LoginResponse
|
||||
* @return LoginResponseDto
|
||||
* @throws AuthException
|
||||
* @throws SPException
|
||||
* @throws EnvironmentIsBrokenException
|
||||
@@ -120,7 +122,7 @@ final class Login extends Service implements LoginService
|
||||
* @uses Login::authLdap()
|
||||
*
|
||||
*/
|
||||
public function doLogin(): LoginResponse
|
||||
public function doLogin(): LoginResponseDto
|
||||
{
|
||||
$user = $this->request->analyzeString('user');
|
||||
$pass = $this->request->analyzeEncrypted('pass');
|
||||
@@ -191,7 +193,7 @@ final class Login extends Service implements LoginService
|
||||
$uri->addParam('r', 'index');
|
||||
}
|
||||
|
||||
return new LoginResponse(self::STATUS_PASS, $uri->getUri());
|
||||
return new LoginResponseDto(self::STATUS_PASS, $uri->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +210,8 @@ final class Login extends Service implements LoginService
|
||||
__u('Internal error'),
|
||||
SPException::ERROR,
|
||||
null,
|
||||
Service::STATUS_INTERNAL_ERROR
|
||||
Service::STATUS_INTERNAL_ERROR,
|
||||
$e
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -216,15 +219,15 @@ final class Login extends Service implements LoginService
|
||||
/**
|
||||
* Comprobar estado del usuario
|
||||
*
|
||||
* @return LoginResponse
|
||||
* @return LoginResponseDto
|
||||
* @throws EnvironmentIsBrokenException
|
||||
* @throws ConstraintException
|
||||
* @throws QueryException
|
||||
* @throws AuthException
|
||||
*/
|
||||
private function checkUser(): LoginResponse
|
||||
private function checkUser(): LoginResponseDto
|
||||
{
|
||||
$userLoginResponse = $this->userLoginData->getUserLoginResponse();
|
||||
$userLoginResponse = $this->userLoginData->getUserDataDto();
|
||||
|
||||
if ($userLoginResponse !== null) {
|
||||
// Comprobar si el usuario está deshabilitado
|
||||
@@ -263,17 +266,19 @@ final class Login extends Service implements LoginService
|
||||
$uri = new Uri('index.php');
|
||||
$uri->addParam('r', 'userPassReset/reset/' . $hash);
|
||||
|
||||
return new LoginResponse(self::STATUS_PASS_RESET, $uri->getUri());
|
||||
return new LoginResponseDto(self::STATUS_PASS_RESET, $uri->getUri());
|
||||
}
|
||||
}
|
||||
|
||||
return new LoginResponse(self::STATUS_NONE);
|
||||
return new LoginResponseDto(self::STATUS_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cargar la clave maestra o solicitarla
|
||||
*
|
||||
* @throws AuthException
|
||||
* @throws CryptException
|
||||
* @throws NoSuchItemException
|
||||
* @throws SPException
|
||||
*/
|
||||
private function loadMasterPass(): void
|
||||
@@ -283,76 +288,21 @@ final class Login extends Service implements LoginService
|
||||
|
||||
try {
|
||||
if ($masterPass) {
|
||||
if ($this->temporaryMasterPassService->checkTempMasterPass($masterPass)) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass.temporary',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Using temporary password')))
|
||||
);
|
||||
|
||||
$masterPass = $this->temporaryMasterPassService->getUsingKey($masterPass);
|
||||
}
|
||||
|
||||
if ($this->userPassService->updateMasterPassOnLogin(
|
||||
$masterPass,
|
||||
$this->userLoginData
|
||||
)->getStatus() !== UserPassService::MPASS_OK
|
||||
) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Wrong master password')))
|
||||
);
|
||||
|
||||
$this->addTracking();
|
||||
|
||||
throw new AuthException(
|
||||
__u('Wrong master password'),
|
||||
SPException::INFO,
|
||||
null,
|
||||
self::STATUS_INVALID_MASTER_PASS
|
||||
);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Master password updated')))
|
||||
);
|
||||
$this->checkMasterPass($masterPass);
|
||||
} elseif ($oldPass) {
|
||||
if ($this->userPassService->updateMasterPassFromOldPass(
|
||||
$oldPass,
|
||||
$this->userLoginData
|
||||
)->getStatus() !== UserPassService::MPASS_OK
|
||||
) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Wrong master password')))
|
||||
);
|
||||
|
||||
$this->addTracking();
|
||||
|
||||
throw new AuthException(
|
||||
__u('Wrong master password'),
|
||||
SPException::INFO,
|
||||
null,
|
||||
self::STATUS_INVALID_MASTER_PASS
|
||||
);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Master password updated')))
|
||||
);
|
||||
$this->loadMasterPassUsingOld($oldPass);
|
||||
} else {
|
||||
switch ($this->userPassService->loadUserMPass($this->userLoginData)->getStatus()) {
|
||||
case UserPassService::MPASS_CHECKOLD:
|
||||
switch ($this->userMasterPassService->load($this->userLoginData)->getUserMasterPassStatus()) {
|
||||
case UserMasterPassStatus::CheckOld:
|
||||
throw new AuthException(
|
||||
__u('Your previous password is needed'),
|
||||
SPException::INFO,
|
||||
null,
|
||||
self::STATUS_NEED_OLD_PASS
|
||||
);
|
||||
case UserPassService::MPASS_NOTSET:
|
||||
case UserPassService::MPASS_CHANGED:
|
||||
case UserPassService::MPASS_WRONG:
|
||||
case UserMasterPassStatus::NotSet:
|
||||
case UserMasterPassStatus::Changed:
|
||||
case UserMasterPassStatus::Invalid:
|
||||
$this->addTracking();
|
||||
|
||||
throw new AuthException(
|
||||
@@ -361,9 +311,15 @@ final class Login extends Service implements LoginService
|
||||
null,
|
||||
self::STATUS_INVALID_MASTER_PASS
|
||||
);
|
||||
case UserMasterPassStatus::Ok:
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Master password loaded')))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (CryptoException $e) {
|
||||
} catch (ServiceException $e) {
|
||||
$this->eventDispatcher->notify('exception', new Event($e));
|
||||
|
||||
throw new AuthException(
|
||||
@@ -376,6 +332,81 @@ final class Login extends Service implements LoginService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $masterPass
|
||||
* @return void
|
||||
* @throws AuthException
|
||||
* @throws NoSuchItemException
|
||||
* @throws ServiceException
|
||||
* @throws CryptException
|
||||
*/
|
||||
private function checkMasterPass(string $masterPass): void
|
||||
{
|
||||
if ($this->temporaryMasterPassService->checkTempMasterPass($masterPass)) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass.temporary',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Using temporary password')))
|
||||
);
|
||||
|
||||
$masterPass = $this->temporaryMasterPassService->getUsingKey($masterPass);
|
||||
}
|
||||
|
||||
if ($this->userMasterPassService->updateOnLogin($masterPass, $this->userLoginData)
|
||||
->getUserMasterPassStatus() !== UserMasterPassStatus::Ok
|
||||
) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Wrong master password')))
|
||||
);
|
||||
|
||||
$this->addTracking();
|
||||
|
||||
throw new AuthException(
|
||||
__u('Wrong master password'),
|
||||
SPException::INFO,
|
||||
null,
|
||||
self::STATUS_INVALID_MASTER_PASS
|
||||
);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Master password updated')))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $oldPass
|
||||
* @return void
|
||||
* @throws AuthException
|
||||
* @throws SPException
|
||||
*/
|
||||
private function loadMasterPassUsingOld(string $oldPass): void
|
||||
{
|
||||
if ($this->userMasterPassService->updateFromOldPass($oldPass, $this->userLoginData)
|
||||
->getUserMasterPassStatus() !== UserMasterPassStatus::Ok
|
||||
) {
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Wrong master password')))
|
||||
);
|
||||
|
||||
$this->addTracking();
|
||||
|
||||
throw new AuthException(
|
||||
__u('Wrong master password'),
|
||||
SPException::INFO,
|
||||
null,
|
||||
self::STATUS_INVALID_MASTER_PASS
|
||||
);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->notify(
|
||||
'login.masterPass',
|
||||
new Event($this, EventMessage::factory()->addDescription(__u('Master password updated')))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cargar la sesión del usuario
|
||||
*
|
||||
@@ -385,26 +416,24 @@ final class Login extends Service implements LoginService
|
||||
*/
|
||||
private function setUserSession(): void
|
||||
{
|
||||
$userLoginResponse = $this->userLoginData->getUserLoginResponse();
|
||||
$userLoginResponse = $this->userLoginData->getUserDataDto();
|
||||
|
||||
// Actualizar el último login del usuario
|
||||
$this->userService->updateLastLoginById($userLoginResponse->getId());
|
||||
|
||||
if ($this->context->getTrasientKey('mpass_updated')) {
|
||||
$userLoginResponse->setLastUpdateMPass(time());
|
||||
}
|
||||
// if ($this->context->getTrasientKey(UserMasterPass::SESSION_MASTERPASS_UPDATED)) {
|
||||
// $this->context->setTrasientKey('user_master_pass_last_update', time());
|
||||
// }
|
||||
|
||||
// Cargar las variables de ussuario en la sesión
|
||||
$this->context->setUserData($userLoginResponse);
|
||||
$this->context->setUserProfile(
|
||||
$this->userProfileService->getById($userLoginResponse->getUserProfileId())->getProfile()
|
||||
$this->userProfileService
|
||||
->getById($userLoginResponse->getUserProfileId())
|
||||
->hydrate(ProfileData::class)
|
||||
);
|
||||
$this->context->setLocale($userLoginResponse->getPreferences()->getLang());
|
||||
|
||||
if ($this->configData->isDemoEnabled()) {
|
||||
$userLoginResponse->setPreferences(new UserPreferences());
|
||||
}
|
||||
|
||||
$this->eventDispatcher->notify(
|
||||
'login.session.load',
|
||||
new Event($this, EventMessage::factory()->addDetail(__u('User'), $userLoginResponse->getLogin()))
|
||||
@@ -426,7 +455,7 @@ final class Login extends Service implements LoginService
|
||||
*/
|
||||
private function cleanUserData(): void
|
||||
{
|
||||
$this->userLoginData->setUserLoginResponse();
|
||||
$this->userLoginData->setUserDataDto();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -27,7 +27,8 @@ namespace SP\Domain\Core\Context;
|
||||
use SP\Core\Context\ContextException;
|
||||
use SP\DataModel\ProfileData;
|
||||
use SP\Domain\Account\Dtos\AccountCacheDto;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Services\UserData;
|
||||
|
||||
/**
|
||||
* Class ContextInterface
|
||||
@@ -58,7 +59,7 @@ interface ContextInterface
|
||||
/**
|
||||
* Establece los datos del usuario en la sesión.
|
||||
*/
|
||||
public function setUserData(?UserLoginResponse $userLoginResponse = null);
|
||||
public function setUserData(?UserDataDto $userDataDto = null);
|
||||
|
||||
/**
|
||||
* Obtiene el objeto de perfil de usuario de la sesión.
|
||||
@@ -78,7 +79,7 @@ interface ContextInterface
|
||||
/**
|
||||
* Devuelve los datos del usuario en la sesión.
|
||||
*/
|
||||
public function getUserData(): UserLoginResponse;
|
||||
public function getUserData(): UserDataDto;
|
||||
|
||||
/**
|
||||
* Establecer el lenguaje de la sesión
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
namespace SP\Domain\Crypt\Ports;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use SP\Domain\Common\Services\ServiceException;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\CryptException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
|
||||
@@ -82,7 +82,7 @@ interface TemporaryMasterPassService
|
||||
* @return string con la clave maestra desencriptada
|
||||
* @throws NoSuchItemException
|
||||
* @throws ServiceException
|
||||
* @throws CryptoException
|
||||
* @throws CryptException
|
||||
*/
|
||||
public function getUsingKey(string $key): string;
|
||||
}
|
||||
|
||||
151
lib/SP/Domain/User/Dtos/UserDataDto.php
Normal file
151
lib/SP/Domain/User/Dtos/UserDataDto.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Dtos;
|
||||
|
||||
use SP\Domain\User\Models\User;
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
|
||||
/**
|
||||
* Class UserLoginResponse
|
||||
*/
|
||||
final readonly class UserDataDto
|
||||
{
|
||||
private ?UserPreferences $preferences;
|
||||
|
||||
public function __construct(private ?User $user = null)
|
||||
{
|
||||
$this->preferences = $this->user?->hydrate(UserPreferences::class);
|
||||
}
|
||||
|
||||
public function getLogin(): ?string
|
||||
{
|
||||
return $this->user->getLogin();
|
||||
}
|
||||
|
||||
public function getSsoLogin(): ?string
|
||||
{
|
||||
return $this->user->getSsoLogin();
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->user->getName();
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->user->getEmail();
|
||||
}
|
||||
|
||||
public function getUserGroupId(): int
|
||||
{
|
||||
return (int)$this->user->getUserGroupId();
|
||||
}
|
||||
|
||||
public function getUserProfileId(): int
|
||||
{
|
||||
return (int)$this->user->getUserProfileId();
|
||||
}
|
||||
|
||||
public function getIsAdminApp(): bool
|
||||
{
|
||||
return (bool)$this->user->isAdminApp();
|
||||
}
|
||||
|
||||
public function getIsAdminAcc(): bool
|
||||
{
|
||||
return (bool)$this->user->isAdminAcc();
|
||||
}
|
||||
|
||||
public function getIsDisabled(): bool
|
||||
{
|
||||
return (bool)$this->user->isDisabled();
|
||||
}
|
||||
|
||||
public function getIsChangePass(): bool
|
||||
{
|
||||
return (bool)$this->user->isChangePass();
|
||||
}
|
||||
|
||||
public function getIsChangedPass(): bool
|
||||
{
|
||||
return (bool)$this->user->isChangedPass();
|
||||
}
|
||||
|
||||
public function getIsLdap(): bool
|
||||
{
|
||||
return (bool)$this->user->isLdap();
|
||||
}
|
||||
|
||||
public function getIsMigrate(): bool
|
||||
{
|
||||
return (bool)$this->user->isMigrate();
|
||||
}
|
||||
|
||||
public function getPreferences(): ?UserPreferences
|
||||
{
|
||||
return $this->preferences;
|
||||
}
|
||||
|
||||
public function getPass(): ?string
|
||||
{
|
||||
return $this->user->getPass();
|
||||
}
|
||||
|
||||
public function getMPass(): ?string
|
||||
{
|
||||
return $this->user->getMPass();
|
||||
}
|
||||
|
||||
public function getMKey(): ?string
|
||||
{
|
||||
return $this->user->getMKey();
|
||||
}
|
||||
|
||||
public function getLastUpdateMPass(): int
|
||||
{
|
||||
return $this->user->getLastUpdateMPass();
|
||||
}
|
||||
|
||||
public function getHashSalt(): ?string
|
||||
{
|
||||
return $this->user->getHashSalt();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->user->getId();
|
||||
}
|
||||
|
||||
public function getUserGroupName(): ?string
|
||||
{
|
||||
return $this->user->offsetGet('userGroup.name');
|
||||
}
|
||||
|
||||
public function getLastUpdate(): int
|
||||
{
|
||||
return (int)strtotime($this->user->getLastUpdate());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -22,37 +22,29 @@
|
||||
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
namespace SP\Domain\User\Dtos;
|
||||
|
||||
use SP\Domain\User\Services\UserMasterPassStatus;
|
||||
|
||||
/**
|
||||
* Class UserPassResponse
|
||||
*
|
||||
* @package SP\DataModel\Dto
|
||||
* Class UserMasterPassDto
|
||||
*/
|
||||
final class UserPassResponse
|
||||
final readonly class UserMasterPassDto
|
||||
{
|
||||
private int $status;
|
||||
private ?string $cryptMasterPass = null;
|
||||
private ?string $cryptSecuredKey = null;
|
||||
private ?string $clearMasterPass;
|
||||
|
||||
/**
|
||||
* UserPassResponse constructor.
|
||||
*/
|
||||
public function __construct(int $status, ?string $clearUserMPass = null)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->clearMasterPass = $clearUserMPass;
|
||||
public function __construct(
|
||||
private UserMasterPassStatus $userMasterPassStatus,
|
||||
private ?string $clearMasterPass = null,
|
||||
private ?string $cryptMasterPass = null,
|
||||
private ?string $cryptSecuredKey = null
|
||||
) {
|
||||
}
|
||||
|
||||
public function getStatus(): int
|
||||
public function getUserMasterPassStatus(): UserMasterPassStatus
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(int $status): void
|
||||
{
|
||||
$this->status = $status;
|
||||
return $this->userMasterPassStatus;
|
||||
}
|
||||
|
||||
public function getCryptMasterPass(): ?string
|
||||
@@ -60,23 +52,13 @@ final class UserPassResponse
|
||||
return $this->cryptMasterPass;
|
||||
}
|
||||
|
||||
public function setCryptMasterPass(string $cryptMasterPass): void
|
||||
{
|
||||
$this->cryptMasterPass = $cryptMasterPass;
|
||||
}
|
||||
|
||||
public function getCryptSecuredKey(): ?string
|
||||
{
|
||||
return $this->cryptSecuredKey;
|
||||
}
|
||||
|
||||
public function setCryptSecuredKey(string $cryptSecuredKey): void
|
||||
{
|
||||
$this->cryptSecuredKey = $cryptSecuredKey;
|
||||
}
|
||||
|
||||
public function getClearMasterPass(): ?string
|
||||
{
|
||||
return $this->clearMasterPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
lib/SP/Domain/User/Ports/UserMasterPassService.php
Normal file
65
lib/SP/Domain/User/Ports/UserMasterPassService.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Ports;
|
||||
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Common\Services\ServiceException;
|
||||
use SP\Domain\User\Dtos\UserMasterPassDto;
|
||||
|
||||
/**
|
||||
* Class UserPassService
|
||||
*
|
||||
* @package SP\Domain\User\Services
|
||||
*/
|
||||
interface UserMasterPassService
|
||||
{
|
||||
/**
|
||||
* Actualizar la clave maestra con la clave anterior del usuario
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function updateFromOldPass(string $oldUserPass, UserLoginDto $userLoginDto): UserMasterPassDto;
|
||||
|
||||
/**
|
||||
* Comprueba la clave maestra del usuario.
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function load(UserLoginDto $userLoginDto, ?string $userPass = null): UserMasterPassDto;
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario al realizar login
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function updateOnLogin(string $userMasterPass, UserLoginDto $userLoginDto): UserMasterPassDto;
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario en la BBDD.
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function create(string $masterPass, string $userLogin, string $userPass): UserMasterPassDto;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Ports;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\User\Services\UserPassResponse;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
|
||||
/**
|
||||
* Class UserPassService
|
||||
*
|
||||
* @package SP\Domain\User\Services
|
||||
*/
|
||||
interface UserPassServiceInterface
|
||||
{
|
||||
/**
|
||||
* Actualizar la clave maestra con la clave anterior del usuario
|
||||
*
|
||||
* @throws SPException
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public function updateMasterPassFromOldPass(string $oldUserPass, UserLoginData $userLoginData): UserPassResponse;
|
||||
|
||||
/**
|
||||
* Comprueba la clave maestra del usuario.
|
||||
*
|
||||
* @throws SPException
|
||||
*/
|
||||
public function loadUserMPass(UserLoginData $userLoginData, ?string $userPass = null): UserPassResponse;
|
||||
|
||||
/**
|
||||
* Obtener una clave de cifrado basada en la clave del usuario y un salt.
|
||||
*
|
||||
* @return string con la clave de cifrado
|
||||
*/
|
||||
public function makeKeyForUser(string $userLogin, string $userPass): string;
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario al realizar login
|
||||
*
|
||||
* @throws SPException
|
||||
* @throws CryptoException
|
||||
* @throws SPException
|
||||
*/
|
||||
public function updateMasterPassOnLogin(string $userMPass, UserLoginData $userLoginData): UserPassResponse;
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario en la BBDD.
|
||||
*
|
||||
* @throws CryptoException
|
||||
* @throws SPException
|
||||
*/
|
||||
public function createMasterPass(string $masterPass, string $userLogin, string $userPass): UserPassResponse;
|
||||
|
||||
/**
|
||||
* @throws ConstraintException
|
||||
* @throws QueryException
|
||||
* @throws NoSuchItemException
|
||||
*/
|
||||
public function migrateUserPassById(int $id, string $userPass): void;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
|
||||
/**
|
||||
* Class UserLoginResponse
|
||||
*
|
||||
* @package SP\Domain\User\Services
|
||||
*/
|
||||
final class UserLoginResponse
|
||||
{
|
||||
private ?int $id = null;
|
||||
private ?string $login = null;
|
||||
private ?string $ssoLogin = null;
|
||||
private ?string $name = null;
|
||||
private ?string $email = null;
|
||||
private int $userGroupId = 0;
|
||||
private ?string $userGroupName = null;
|
||||
private int $userProfileId = 0;
|
||||
private bool $isAdminApp = false;
|
||||
private bool $isAdminAcc = false;
|
||||
private bool $isDisabled = false;
|
||||
private bool $isChangePass = false;
|
||||
private bool $isChangedPass = false;
|
||||
private bool $isLdap = false;
|
||||
private bool $isMigrate = false;
|
||||
private ?UserPreferences $preferences = null;
|
||||
private ?string $pass = null;
|
||||
private ?string $hashSalt = null;
|
||||
private ?string $mPass = null;
|
||||
private ?string $mKey = null;
|
||||
private int $lastUpdateMPass = 0;
|
||||
private ?int $lastUpdate = null;
|
||||
|
||||
public function getLogin(): ?string
|
||||
{
|
||||
return $this->login;
|
||||
}
|
||||
|
||||
public function setLogin(string $login): UserLoginResponse
|
||||
{
|
||||
$this->login = $login;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSsoLogin(): ?string
|
||||
{
|
||||
return $this->ssoLogin;
|
||||
}
|
||||
|
||||
public function setSsoLogin(?string $ssoLogin): UserLoginResponse
|
||||
{
|
||||
$this->ssoLogin = $ssoLogin;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): UserLoginResponse
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(?string $email): UserLoginResponse
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserGroupId(): int
|
||||
{
|
||||
return $this->userGroupId;
|
||||
}
|
||||
|
||||
public function setUserGroupId(int $userGroupId): UserLoginResponse
|
||||
{
|
||||
$this->userGroupId = $userGroupId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserProfileId(): int
|
||||
{
|
||||
return $this->userProfileId;
|
||||
}
|
||||
|
||||
public function setUserProfileId(int $userProfileId): UserLoginResponse
|
||||
{
|
||||
$this->userProfileId = $userProfileId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsAdminApp(): bool
|
||||
{
|
||||
return $this->isAdminApp;
|
||||
}
|
||||
|
||||
public function setIsAdminApp(bool $isAdminApp): UserLoginResponse
|
||||
{
|
||||
$this->isAdminApp = $isAdminApp;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsAdminAcc(): bool
|
||||
{
|
||||
return $this->isAdminAcc;
|
||||
}
|
||||
|
||||
public function setIsAdminAcc(bool $isAdminAcc): UserLoginResponse
|
||||
{
|
||||
$this->isAdminAcc = $isAdminAcc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsDisabled(): bool
|
||||
{
|
||||
return $this->isDisabled;
|
||||
}
|
||||
|
||||
public function setIsDisabled(bool $isDisabled): UserLoginResponse
|
||||
{
|
||||
$this->isDisabled = $isDisabled;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsChangePass(): bool
|
||||
{
|
||||
return $this->isChangePass;
|
||||
}
|
||||
|
||||
public function setIsChangePass(bool $isChangePass): UserLoginResponse
|
||||
{
|
||||
$this->isChangePass = $isChangePass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsChangedPass(): bool
|
||||
{
|
||||
return $this->isChangedPass;
|
||||
}
|
||||
|
||||
public function setIsChangedPass(bool $isChangedPass): UserLoginResponse
|
||||
{
|
||||
$this->isChangedPass = $isChangedPass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsLdap(): bool
|
||||
{
|
||||
return $this->isLdap;
|
||||
}
|
||||
|
||||
public function setIsLdap(bool $isLdap): UserLoginResponse
|
||||
{
|
||||
$this->isLdap = $isLdap;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsMigrate(): bool
|
||||
{
|
||||
return $this->isMigrate;
|
||||
}
|
||||
|
||||
public function setIsMigrate(bool $isMigrate): UserLoginResponse
|
||||
{
|
||||
$this->isMigrate = $isMigrate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPreferences(): ?UserPreferences
|
||||
{
|
||||
return $this->preferences;
|
||||
}
|
||||
|
||||
public function setPreferences(UserPreferences $preferences): UserLoginResponse
|
||||
{
|
||||
$this->preferences = $preferences;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPass(): ?string
|
||||
{
|
||||
return $this->pass;
|
||||
}
|
||||
|
||||
public function setPass(string $pass): UserLoginResponse
|
||||
{
|
||||
$this->pass = $pass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMPass(): ?string
|
||||
{
|
||||
return $this->mPass;
|
||||
}
|
||||
|
||||
public function setMPass(string $mPass): UserLoginResponse
|
||||
{
|
||||
$this->mPass = $mPass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMKey(): ?string
|
||||
{
|
||||
return $this->mKey;
|
||||
}
|
||||
|
||||
public function setMKey(string $mKey): UserLoginResponse
|
||||
{
|
||||
$this->mKey = $mKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLastUpdateMPass(): int
|
||||
{
|
||||
return $this->lastUpdateMPass;
|
||||
}
|
||||
|
||||
public function setLastUpdateMPass(int $lastUpdateMPass): UserLoginResponse
|
||||
{
|
||||
$this->lastUpdateMPass = $lastUpdateMPass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHashSalt(): ?string
|
||||
{
|
||||
return $this->hashSalt;
|
||||
}
|
||||
|
||||
public function setHashSalt(string $hashSalt): UserLoginResponse
|
||||
{
|
||||
$this->hashSalt = $hashSalt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(int $id): UserLoginResponse
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserGroupName(): ?string
|
||||
{
|
||||
return $this->userGroupName;
|
||||
}
|
||||
|
||||
public function setUserGroupName(string $userGroupName): UserLoginResponse
|
||||
{
|
||||
$this->userGroupName = $userGroupName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getLastUpdate(): int
|
||||
{
|
||||
return $this->lastUpdate;
|
||||
}
|
||||
|
||||
public function setLastUpdate(int $lastUpdate): UserLoginResponse
|
||||
{
|
||||
$this->lastUpdate = $lastUpdate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
212
lib/SP/Domain/User/Services/UserMasterPass.php
Normal file
212
lib/SP/Domain/User/Services/UserMasterPass.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
|
||||
use Exception;
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Common\Services\Service;
|
||||
use SP\Domain\Common\Services\ServiceException;
|
||||
use SP\Domain\Config\Ports\ConfigService;
|
||||
use SP\Domain\Core\Crypt\CryptInterface;
|
||||
use SP\Domain\Core\Exceptions\CryptException;
|
||||
use SP\Domain\User\Dtos\UserMasterPassDto;
|
||||
use SP\Domain\User\Ports\UserMasterPassService;
|
||||
use SP\Domain\User\Ports\UserRepository;
|
||||
|
||||
use function SP\__u;
|
||||
|
||||
/**
|
||||
* Class UserMasterPass
|
||||
*/
|
||||
final class UserMasterPass extends Service implements UserMasterPassService
|
||||
{
|
||||
// public const SESSION_MASTERPASS_UPDATED = 'mpass_updated';
|
||||
|
||||
private const PARAM_MASTER_PWD = 'masterPwd';
|
||||
private const PARAM_LASTUPDATEMPASS = 'lastupdatempass';
|
||||
|
||||
public function __construct(
|
||||
Application $application,
|
||||
private readonly UserRepository $userRepository,
|
||||
private readonly ConfigService $configService,
|
||||
private readonly CryptInterface $crypt
|
||||
) {
|
||||
parent::__construct($application);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the master pass by using the old user's password
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function updateFromOldPass(string $oldUserPass, UserLoginDto $userLoginDto): UserMasterPassDto
|
||||
{
|
||||
$response = $this->load($userLoginDto, $oldUserPass);
|
||||
|
||||
if ($response->getUserMasterPassStatus() === UserMasterPassStatus::Ok) {
|
||||
return $this->updateOnLogin($response->getClearMasterPass(), $userLoginDto);
|
||||
}
|
||||
|
||||
return new UserMasterPassDto(UserMasterPassStatus::Invalid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the user's master pass
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function load(UserLoginDto $userLoginDto, ?string $userPass = null): UserMasterPassDto
|
||||
{
|
||||
try {
|
||||
if (($userDataDto = $userLoginDto->getUserDataDto()) === null
|
||||
|| empty($userDataDto->getMPass())
|
||||
|| empty($userDataDto->getMKey())
|
||||
|| empty($systemMasterPassHash = $this->configService->getByParam(self::PARAM_MASTER_PWD))
|
||||
) {
|
||||
return new UserMasterPassDto(UserMasterPassStatus::NotSet);
|
||||
}
|
||||
|
||||
if ($userDataDto->getLastUpdateMPass() <
|
||||
(int)$this->configService->getByParam(self::PARAM_LASTUPDATEMPASS, 0)
|
||||
) {
|
||||
return new UserMasterPassDto(UserMasterPassStatus::Changed);
|
||||
}
|
||||
|
||||
if ($userPass === null && $userDataDto->getIsChangedPass()) {
|
||||
return new UserMasterPassDto(UserMasterPassStatus::CheckOld);
|
||||
}
|
||||
|
||||
|
||||
$key = $this->makeKeyForUser($userLoginDto->getLoginUser(), $userPass ?? $userLoginDto->getLoginPass());
|
||||
|
||||
$userMasterPass = $this->crypt->decrypt($userDataDto->getMPass(), $userDataDto->getMKey(), $key);
|
||||
|
||||
// Comprobamos el hash de la clave del usuario con la guardada
|
||||
if (Hash::checkHashKey($userMasterPass, $systemMasterPassHash)) {
|
||||
$this->setMasterKeyInContext($userMasterPass);
|
||||
|
||||
return new UserMasterPassDto(
|
||||
UserMasterPassStatus::Ok,
|
||||
$userMasterPass,
|
||||
$userDataDto->getMPass(),
|
||||
$userDataDto->getMKey()
|
||||
);
|
||||
}
|
||||
} catch (CryptException $e) {
|
||||
$this->eventDispatcher->notify('exception', new Event($e));
|
||||
|
||||
return new UserMasterPassDto(UserMasterPassStatus::CheckOld);
|
||||
} catch (Exception $e) {
|
||||
throw ServiceException::from($e);
|
||||
}
|
||||
|
||||
return new UserMasterPassDto(UserMasterPassStatus::Invalid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener una clave de cifrado basada en la clave del usuario y un salt.
|
||||
*
|
||||
* @return string con la clave de cifrado
|
||||
*/
|
||||
private function makeKeyForUser(string $userLogin, string $userPass): string
|
||||
{
|
||||
return trim($userPass . $userLogin . $this->config->getConfigData()->getPasswordSalt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's master pass on log in.
|
||||
* It requires the user's login data to build a secure key to store the master password
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function updateOnLogin(string $userMasterPass, UserLoginDto $userLoginDto): UserMasterPassDto
|
||||
{
|
||||
try {
|
||||
$userData = $userLoginDto->getUserDataDto();
|
||||
$systemMasterPassHash = $this->configService->getByParam(self::PARAM_MASTER_PWD);
|
||||
|
||||
if (null === $systemMasterPassHash) {
|
||||
$systemMasterPassHash = Hash::hashKey($userMasterPass);
|
||||
|
||||
$this->configService->save(self::PARAM_MASTER_PWD, $systemMasterPassHash);
|
||||
}
|
||||
|
||||
if (Hash::checkHashKey($userMasterPass, $systemMasterPassHash)) {
|
||||
$response = $this->create(
|
||||
$userMasterPass,
|
||||
$userLoginDto->getLoginUser(),
|
||||
$userLoginDto->getLoginPass()
|
||||
);
|
||||
|
||||
$this->userRepository->updateMasterPassById(
|
||||
$userData->getId(),
|
||||
$response->getCryptMasterPass(),
|
||||
$response->getCryptSecuredKey()
|
||||
);
|
||||
|
||||
// $this->context->setTrasientKey(self::SESSION_MASTERPASS_UPDATED, true);
|
||||
|
||||
$this->setMasterKeyInContext($userMasterPass);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return new UserMasterPassDto(UserMasterPassStatus::Invalid);
|
||||
} catch (Exception $e) {
|
||||
throw ServiceException::from($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario en la BBDD.
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function create(string $masterPass, string $userLogin, string $userPass): UserMasterPassDto
|
||||
{
|
||||
$key = $this->makeKeyForUser($userLogin, $userPass);
|
||||
|
||||
try {
|
||||
$securedKey = $this->crypt->makeSecuredKey($key);
|
||||
|
||||
if (strlen($securedKey) > 1000) {
|
||||
throw ServiceException::error(__u('Internal error'), null, Service::STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
$encryptedMasterPass = $this->crypt->encrypt($masterPass, $securedKey, $key);
|
||||
|
||||
if (strlen($encryptedMasterPass) > 1000) {
|
||||
throw ServiceException::error(__u('Internal error'), null, Service::STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
return new UserMasterPassDto(UserMasterPassStatus::Ok, $masterPass, $encryptedMasterPass, $securedKey);
|
||||
} catch (CryptException $e) {
|
||||
throw ServiceException::from($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
lib/SP/Domain/User/Services/UserMasterPassStatus.php
Normal file
37
lib/SP/Domain/User/Services/UserMasterPassStatus.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
|
||||
/**
|
||||
* Enum UserMasterPassStatus
|
||||
*/
|
||||
enum UserMasterPassStatus
|
||||
{
|
||||
case Invalid;
|
||||
case Ok;
|
||||
case NotSet;
|
||||
case Changed;
|
||||
case CheckOld;
|
||||
}
|
||||
71
lib/SP/Domain/User/Services/UserPass.php
Normal file
71
lib/SP/Domain/User/Services/UserPass.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\Domain\Common\Services\Service;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\User\Models\User;
|
||||
use SP\Domain\User\Ports\UserRepository;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
|
||||
use function SP\__u;
|
||||
|
||||
/**
|
||||
* Class UserPass
|
||||
*/
|
||||
final class UserPass extends Service implements UserPassService
|
||||
{
|
||||
public function __construct(
|
||||
Application $application,
|
||||
private readonly UserRepository $userRepository
|
||||
) {
|
||||
parent::__construct($application);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ConstraintException
|
||||
* @throws QueryException
|
||||
* @throws NoSuchItemException
|
||||
*/
|
||||
public function migrateUserPassById(int $id, string $userPass): void
|
||||
{
|
||||
$user = new User(
|
||||
[
|
||||
'id' => $id,
|
||||
'pass' => Hash::hashKey($userPass),
|
||||
'isChangePass' => 0,
|
||||
'isChangedPass' => 1,
|
||||
'isMigrate' => 0
|
||||
]
|
||||
);
|
||||
|
||||
if ($this->userRepository->updatePassById($user) === 0) {
|
||||
throw NoSuchItemException::info(__u('User does not exist'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,228 +24,19 @@
|
||||
|
||||
namespace SP\Domain\User\Services;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use SP\Core\Application;
|
||||
use SP\Core\Crypt\Crypt;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Common\Services\Service;
|
||||
use SP\Domain\Config\Ports\ConfigService;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\User\Ports\UserPassServiceInterface;
|
||||
use SP\Domain\User\Ports\UserRepository;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
|
||||
/**
|
||||
* Class UserPassService
|
||||
*
|
||||
* @package SP\Domain\User\Services
|
||||
* Class UserPass
|
||||
*/
|
||||
final class UserPassService extends Service implements UserPassServiceInterface
|
||||
interface UserPassService
|
||||
{
|
||||
// La clave maestra incorrecta
|
||||
public const MPASS_WRONG = 0;
|
||||
// La clave maestra correcta
|
||||
public const MPASS_OK = 1;
|
||||
// La clave maestra no está guardada
|
||||
public const MPASS_NOTSET = 2;
|
||||
// La clave maestra ha cambiado
|
||||
public const MPASS_CHANGED = 3;
|
||||
// Comprobar la clave maestra con la clave del usuario anterior
|
||||
public const MPASS_CHECKOLD = 4;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
private ConfigService $configService;
|
||||
|
||||
public function __construct(
|
||||
Application $application,
|
||||
UserRepository $userRepository,
|
||||
ConfigService $configService
|
||||
) {
|
||||
parent::__construct($application);
|
||||
|
||||
$this->userRepository = $userRepository;
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra con la clave anterior del usuario
|
||||
*
|
||||
* @throws SPException
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public function updateMasterPassFromOldPass(
|
||||
string $oldUserPass,
|
||||
UserLoginData $userLoginData
|
||||
): UserPassResponse {
|
||||
$response = $this->loadUserMPass($userLoginData, $oldUserPass);
|
||||
|
||||
if ($response->getStatus() === self::MPASS_OK) {
|
||||
return $this->updateMasterPassOnLogin($response->getClearMasterPass(), $userLoginData);
|
||||
}
|
||||
|
||||
return new UserPassResponse(self::MPASS_WRONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comprueba la clave maestra del usuario.
|
||||
*
|
||||
* @throws SPException
|
||||
*/
|
||||
public function loadUserMPass(
|
||||
UserLoginData $userLoginData,
|
||||
?string $userPass = null
|
||||
): UserPassResponse {
|
||||
$userLoginResponse = $userLoginData->getUserLoginResponse();
|
||||
|
||||
$configHashMPass = $this->configService->getByParam('masterPwd');
|
||||
|
||||
if (empty($configHashMPass)
|
||||
|| $userLoginResponse === null
|
||||
|| empty($userLoginResponse->getMPass())
|
||||
|| empty($userLoginResponse->getMKey())
|
||||
) {
|
||||
return new UserPassResponse(self::MPASS_NOTSET);
|
||||
}
|
||||
|
||||
if ($userLoginResponse->getLastUpdateMPass() < $this->configService->getByParam('lastupdatempass')) {
|
||||
return new UserPassResponse(self::MPASS_CHANGED);
|
||||
}
|
||||
|
||||
if ($userPass === null && $userLoginResponse->getIsChangedPass()) {
|
||||
return new UserPassResponse(self::MPASS_CHECKOLD);
|
||||
}
|
||||
|
||||
try {
|
||||
$key = $this->makeKeyForUser(
|
||||
$userLoginData->getLoginUser(),
|
||||
$userPass ?: $userLoginData->getLoginPass()
|
||||
);
|
||||
|
||||
$clearMPass = Crypt::decrypt(
|
||||
$userLoginResponse->getMPass(),
|
||||
$userLoginResponse->getMKey(),
|
||||
$key
|
||||
);
|
||||
|
||||
// Comprobamos el hash de la clave del usuario con la guardada
|
||||
if (Hash::checkHashKey($clearMPass, $configHashMPass)) {
|
||||
$this->setMasterKeyInContext($clearMPass);
|
||||
|
||||
$response = new UserPassResponse(self::MPASS_OK, $clearMPass);
|
||||
$response->setCryptMasterPass($userLoginResponse->getMPass());
|
||||
$response->setCryptSecuredKey($userLoginResponse->getMKey());
|
||||
|
||||
return $response;
|
||||
}
|
||||
} catch (CryptoException $e) {
|
||||
return new UserPassResponse(self::MPASS_CHECKOLD);
|
||||
}
|
||||
|
||||
return new UserPassResponse(self::MPASS_WRONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener una clave de cifrado basada en la clave del usuario y un salt.
|
||||
*
|
||||
* @return string con la clave de cifrado
|
||||
*/
|
||||
public function makeKeyForUser(string $userLogin, string $userPass): string
|
||||
{
|
||||
return trim($userPass . $userLogin . $this->config->getConfigData()->getPasswordSalt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario al realizar login
|
||||
*
|
||||
* @throws SPException
|
||||
* @throws CryptoException
|
||||
* @throws SPException
|
||||
*/
|
||||
public function updateMasterPassOnLogin(string $userMPass, UserLoginData $userLoginData): UserPassResponse
|
||||
{
|
||||
$userData = $userLoginData->getUserLoginResponse();
|
||||
$configHashMPass = $this->configService->getByParam('masterPwd');
|
||||
|
||||
if ($configHashMPass === false) {
|
||||
return new UserPassResponse(self::MPASS_NOTSET);
|
||||
}
|
||||
|
||||
if (null === $configHashMPass) {
|
||||
$configHashMPass = Hash::hashKey($userMPass);
|
||||
|
||||
$this->configService->save('masterPwd', $configHashMPass);
|
||||
}
|
||||
|
||||
if (Hash::checkHashKey($userMPass, $configHashMPass)) {
|
||||
$response = $this->createMasterPass(
|
||||
$userMPass,
|
||||
$userLoginData->getLoginUser(),
|
||||
$userLoginData->getLoginPass()
|
||||
);
|
||||
|
||||
$this->userRepository->updateMasterPassById(
|
||||
$userData->getId(),
|
||||
$response->getCryptMasterPass(),
|
||||
$response->getCryptSecuredKey()
|
||||
);
|
||||
|
||||
// Tells that the master password has been updated
|
||||
$this->context->setTrasientKey('mpass_updated', true);
|
||||
|
||||
$this->setMasterKeyInContext($userMPass);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return new UserPassResponse(self::MPASS_WRONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualizar la clave maestra del usuario en la BBDD.
|
||||
*
|
||||
* @throws CryptoException
|
||||
* @throws SPException
|
||||
*/
|
||||
public function createMasterPass(string $masterPass, string $userLogin, string $userPass): UserPassResponse
|
||||
{
|
||||
$key = $this->makeKeyForUser($userLogin, $userPass);
|
||||
|
||||
$securedKey = Crypt::makeSecuredKey($key);
|
||||
$cryptMPass = Crypt::encrypt($masterPass, $securedKey, $key);
|
||||
|
||||
if (strlen($securedKey) > 1000 || strlen($cryptMPass) > 1000) {
|
||||
throw new SPException(
|
||||
__u('Internal error'),
|
||||
SPException::ERROR,
|
||||
'',
|
||||
Service::STATUS_INTERNAL_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$response = new UserPassResponse(self::MPASS_OK, $masterPass);
|
||||
$response->setCryptMasterPass($cryptMPass);
|
||||
$response->setCryptSecuredKey($securedKey);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ConstraintException
|
||||
* @throws QueryException
|
||||
* @throws NoSuchItemException
|
||||
*/
|
||||
public function migrateUserPassById(int $id, string $userPass): void
|
||||
{
|
||||
$updatePassById = $this->userRepository->updatePassById(
|
||||
$id,
|
||||
new UpdatePassRequest(Hash::hashKey($userPass))
|
||||
);
|
||||
|
||||
if ($updatePassById === 0) {
|
||||
throw new NoSuchItemException(__u('User does not exist'));
|
||||
}
|
||||
}
|
||||
public function migrateUserPassById(int $id, string $userPass): void;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\User\Models\User as UserModel;
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
use SP\Domain\User\Ports\UserPassServiceInterface;
|
||||
use SP\Domain\User\Ports\UserMasterPassService;
|
||||
use SP\Domain\User\Ports\UserRepository;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Infrastructure\Common\Repositories\DuplicatedItemException;
|
||||
@@ -53,13 +53,13 @@ final class UserService extends Service implements UserServiceInterface
|
||||
{
|
||||
use ServiceItemTrait;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
private UserPassServiceInterface $userPassService;
|
||||
private UserRepository $userRepository;
|
||||
private UserMasterPassService $userPassService;
|
||||
|
||||
public function __construct(
|
||||
Application $application,
|
||||
UserRepository $userRepository,
|
||||
UserPassServiceInterface $userPassService
|
||||
Application $application,
|
||||
UserRepository $userRepository,
|
||||
UserMasterPassService $userPassService
|
||||
) {
|
||||
parent::__construct($application);
|
||||
|
||||
@@ -67,33 +67,6 @@ final class UserService extends Service implements UserServiceInterface
|
||||
$this->userPassService = $userPassService;
|
||||
}
|
||||
|
||||
public static function mapUserLoginResponse(
|
||||
UserModel $user
|
||||
): UserLoginResponse {
|
||||
// TODO: create static method UserLoginResponse::from($user)
|
||||
return (new UserLoginResponse())->setId($user->getId())
|
||||
->setName($user->getName())
|
||||
->setLogin($user->getLogin())
|
||||
->setSsoLogin($user->getSsoLogin())
|
||||
->setEmail($user->getEmail())
|
||||
->setPass($user->getPass())
|
||||
->setHashSalt($user->getHashSalt())
|
||||
->setMPass($user->getMPass())
|
||||
->setMKey($user->getMKey())
|
||||
->setLastUpdateMPass($user->getLastUpdateMPass())
|
||||
->setUserGroupId($user->getUserGroupId())
|
||||
->setUserProfileId($user->getUserProfileId())
|
||||
->setPreferences(self::getUserPreferences($user->getPreferences()))
|
||||
->setIsLdap($user->isLdap())
|
||||
->setIsAdminAcc($user->isAdminAcc())
|
||||
->setIsAdminApp($user->isAdminApp())
|
||||
->setIsMigrate($user->isMigrate())
|
||||
->setIsChangedPass($user->isChangedPass())
|
||||
->setIsChangePass($user->isChangePass())
|
||||
->setIsDisabled($user->isDisabled())
|
||||
->setLastUpdate((int)strtotime($user->getLastUpdate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user's preferences object
|
||||
*/
|
||||
@@ -251,7 +224,7 @@ final class UserService extends Service implements UserServiceInterface
|
||||
*/
|
||||
public function createWithMasterPass(UserModel $itemData, string $userPass, string $masterPass): int
|
||||
{
|
||||
$response = $this->userPassService->createMasterPass(
|
||||
$response = $this->userPassService->create(
|
||||
$masterPass,
|
||||
$itemData->getLogin(),
|
||||
$userPass
|
||||
|
||||
@@ -130,10 +130,9 @@ final class User extends BaseRepository implements UserRepository
|
||||
$query = $this->queryFactory
|
||||
->newUpdate()
|
||||
->table(UserModel::TABLE)
|
||||
->cols($user->toArray(['pass', 'isChangePass', 'isChangedPass']))
|
||||
->cols($user->toArray(['pass', 'isChangePass', 'isChangedPass', 'isMigrate']))
|
||||
->set('lastUpdate', 'NOW()')
|
||||
->set('hashSalt', '')
|
||||
->set('isMigrate', 0)
|
||||
->where('id = :id', ['id' => $user->getId()])
|
||||
->limit(1);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace SP\Providers\Auth;
|
||||
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
|
||||
/**
|
||||
* Interface AuthInterface
|
||||
@@ -37,10 +37,10 @@ interface AuthInterface
|
||||
/**
|
||||
* Authenticate using user's data
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
* @return T
|
||||
*/
|
||||
public function authenticate(UserLoginData $userLoginData): AuthDataBase;
|
||||
public function authenticate(UserLoginDto $userLoginData): AuthDataBase;
|
||||
|
||||
/**
|
||||
* Indica si es requerida para acceder a la aplicación
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace SP\Providers\Auth;
|
||||
|
||||
use SP\Core\Application;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Auth\Services\AuthException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Providers\Provider;
|
||||
@@ -87,11 +87,11 @@ class AuthProvider extends Provider implements AuthProviderInterface
|
||||
/**
|
||||
* Probar los métodos de autentificación
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
*
|
||||
* @return false|AuthResult[]
|
||||
*/
|
||||
public function doAuth(UserLoginData $userLoginData): array|bool
|
||||
public function doAuth(UserLoginDto $userLoginData): array|bool
|
||||
{
|
||||
$authsResult = [];
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
namespace SP\Providers\Auth;
|
||||
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Services\AuthException;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
|
||||
/**
|
||||
* Class Auth
|
||||
@@ -39,9 +38,9 @@ interface AuthProviderInterface
|
||||
/**
|
||||
* Probar los métodos de autentificación
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
*
|
||||
* @return false|AuthResult[]
|
||||
*/
|
||||
public function doAuth(UserLoginData $userLoginData): array|bool;
|
||||
public function doAuth(UserLoginDto $userLoginData): array|bool;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace SP\Providers\Auth\Browser;
|
||||
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
use SP\Domain\Http\RequestInterface;
|
||||
use SP\Providers\Auth\AuthInterface;
|
||||
@@ -50,10 +50,10 @@ final class BrowserAuth implements BrowserAuthInterface
|
||||
/**
|
||||
* Authenticate using user's data
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
* @return BrowserAuthData
|
||||
*/
|
||||
public function authenticate(UserLoginData $userLoginData): BrowserAuthData
|
||||
public function authenticate(UserLoginDto $userLoginData): BrowserAuthData
|
||||
{
|
||||
$browserAuthData = new BrowserAuthData($this->isAuthGranted());
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -26,36 +26,31 @@ namespace SP\Providers\Auth\Database;
|
||||
|
||||
use Exception;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\User\Ports\UserPassServiceInterface;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Services\UserService;
|
||||
use SP\Domain\User\Services\UserPassService;
|
||||
|
||||
use function SP\processException;
|
||||
|
||||
/**
|
||||
* Class Database
|
||||
*
|
||||
* Autentificación basada en base de datos
|
||||
*
|
||||
* @package SP\Providers\Auth\Database
|
||||
* Class DatabaseAuth
|
||||
*/
|
||||
final class DatabaseAuth implements DatabaseAuthInterface
|
||||
final readonly class DatabaseAuth implements DatabaseAuthService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserServiceInterface $userService,
|
||||
private readonly UserPassServiceInterface $userPassService
|
||||
private UserServiceInterface $userService,
|
||||
private UserPassService $userPassService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate using user's data
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
* @return DatabaseAuthData
|
||||
*/
|
||||
public function authenticate(UserLoginData $userLoginData): DatabaseAuthData
|
||||
public function authenticate(UserLoginDto $userLoginData): DatabaseAuthData
|
||||
{
|
||||
$authData = new DatabaseAuthData($this->isAuthGranted());
|
||||
|
||||
@@ -72,17 +67,14 @@ final class DatabaseAuth implements DatabaseAuthInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function authUser(UserLoginData $userLoginData): bool
|
||||
private function authUser(UserLoginDto $userLoginData): bool
|
||||
{
|
||||
try {
|
||||
$userLoginResponse =
|
||||
UserService::mapUserLoginResponse($this->userService->getByLogin($userLoginData->getLoginUser()));
|
||||
$userLoginResponse = new UserDataDto($this->userService->getByLogin($userLoginData->getLoginUser()));
|
||||
|
||||
$userLoginData->setUserLoginResponse($userLoginResponse);
|
||||
$userLoginData->setUserDataDto($userLoginResponse);
|
||||
|
||||
if ($userLoginResponse->getIsMigrate()
|
||||
&& $this->checkMigrateUser($userLoginResponse, $userLoginData)
|
||||
) {
|
||||
if ($userLoginResponse->getIsMigrate() && $this->checkMigrateUser($userLoginResponse, $userLoginData)) {
|
||||
$this->userPassService->migrateUserPassById(
|
||||
$userLoginResponse->getId(),
|
||||
$userLoginData->getLoginPass()
|
||||
@@ -99,7 +91,7 @@ final class DatabaseAuth implements DatabaseAuthInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function checkMigrateUser(UserLoginResponse $userLoginResponse, UserLoginData $userLoginData): bool
|
||||
private function checkMigrateUser(UserDataDto $userLoginResponse, UserLoginDto $userLoginData): bool
|
||||
{
|
||||
$passHashSha = sha1($userLoginResponse->getHashSalt() . $userLoginData->getLoginPass());
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace SP\Providers\Auth\Database;
|
||||
|
||||
|
||||
use SP\Providers\Auth\AuthInterface;
|
||||
|
||||
/**
|
||||
@@ -34,7 +33,7 @@ use SP\Providers\Auth\AuthInterface;
|
||||
*
|
||||
* @extends AuthInterface<DatabaseAuthData>
|
||||
*/
|
||||
interface DatabaseAuthInterface extends AuthInterface
|
||||
interface DatabaseAuthService extends AuthInterface
|
||||
{
|
||||
/**
|
||||
* Indica si es requerida para acceder a la aplicación
|
||||
@@ -27,7 +27,7 @@ namespace SP\Providers\Auth\Ldap;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Core\Events\EventDispatcher;
|
||||
use SP\Core\Events\EventMessage;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Auth\Ports\LdapAuthService;
|
||||
use SP\Domain\Auth\Ports\LdapService;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
@@ -60,10 +60,10 @@ final class LdapAuth implements LdapAuthService
|
||||
/**
|
||||
* Authenticate using user's data
|
||||
*
|
||||
* @param UserLoginData $userLoginData
|
||||
* @param UserLoginDto $userLoginData
|
||||
* @return LdapAuthData
|
||||
*/
|
||||
public function authenticate(UserLoginData $userLoginData): LdapAuthData
|
||||
public function authenticate(UserLoginDto $userLoginData): LdapAuthData
|
||||
{
|
||||
$ldapAuthData = new LdapAuthData($this->isAuthGranted());
|
||||
|
||||
|
||||
@@ -29,8 +29,9 @@ use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\Core\Language;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
use SP\Domain\Http\RequestInterface;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Models\User;
|
||||
use SP\Domain\User\Models\UserPreferences;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
/**
|
||||
@@ -78,9 +79,10 @@ class LanguageTest extends UnitaryTestCase
|
||||
->method('getSiteLang')
|
||||
->willReturn(self::$faker->locale);
|
||||
|
||||
$userData = $this->context->getUserData();
|
||||
$user = (new User(['id' => self::$faker->randomNumber(2)]))
|
||||
->dehydrate(new UserPreferences(['lang' => $locale]));
|
||||
|
||||
$userData->setPreferences(new UserPreferences(['lang' => $locale]));
|
||||
$this->context->setUserData(new UserDataDto($user));
|
||||
|
||||
$this->language->setLanguage(true);
|
||||
|
||||
@@ -96,7 +98,8 @@ class LanguageTest extends UnitaryTestCase
|
||||
$appLocale = 'en_US';
|
||||
|
||||
$this->context->setLocale($locale);
|
||||
$this->context->setUserData(new UserLoginResponse());
|
||||
|
||||
$this->context->setUserData(new UserDataDto(new User()));
|
||||
|
||||
$this->configData
|
||||
->expects(self::once())
|
||||
@@ -117,7 +120,8 @@ class LanguageTest extends UnitaryTestCase
|
||||
$browserLocale = 'en_US';
|
||||
|
||||
$this->context->setLocale($locale);
|
||||
$this->context->setUserData(new UserLoginResponse());
|
||||
|
||||
$this->context->setUserData(new UserDataDto(new User()));
|
||||
|
||||
$this->configData
|
||||
->expects(self::once())
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -33,7 +33,7 @@ use SP\Core\UI\Theme;
|
||||
use SP\Domain\Core\Context\SessionContextInterface;
|
||||
use SP\Domain\Core\UI\ThemeContextInterface;
|
||||
use SP\Domain\Core\UI\ThemeIconsInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
@@ -88,21 +88,18 @@ class ThemeTest extends UnitaryTestCase
|
||||
->method('isLoggedIn')
|
||||
->willReturn(true);
|
||||
|
||||
$userLoginResponse = new UserLoginResponse();
|
||||
$userPreferencesData = UserDataGenerator::factory()->buildUserPreferencesData();
|
||||
|
||||
$userLoginResponse->setPreferences($userPreferencesData);
|
||||
$userDataDto = new UserDataDto(UserDataGenerator::factory()->buildUserData());
|
||||
|
||||
$context->expects(self::once())
|
||||
->method('getUserData')
|
||||
->willReturn($userLoginResponse);
|
||||
->willReturn($userDataDto);
|
||||
|
||||
$configData = $this->config->getConfigData();
|
||||
$configData->setSiteTheme(self::$faker->colorName);
|
||||
|
||||
$current = Theme::getThemeName($this->config->getConfigData(), $context);
|
||||
|
||||
$this->assertEquals($userPreferencesData->getTheme(), $current);
|
||||
$this->assertEquals($userDataDto->getPreferences()->getTheme(), $current);
|
||||
}
|
||||
|
||||
public function testGetViewsPath()
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace SPT\Domain\Account\Services;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\Exception;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\Core\Acl\Acl;
|
||||
use SP\DataModel\Item;
|
||||
use SP\Domain\Account\Adapters\AccountPermission;
|
||||
@@ -38,8 +39,11 @@ use SP\Domain\Core\Acl\ActionsInterface;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Storage\Ports\FileCacheService;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Models\User;
|
||||
use SP\Domain\User\Ports\UserToUserGroupServiceInterface;
|
||||
use SP\Infrastructure\File\FileException;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
/**
|
||||
@@ -62,8 +66,9 @@ class AccountAclTest extends UnitaryTestCase
|
||||
AclActionsInterface::ACCOUNT_COPY_PASS,
|
||||
AclActionsInterface::ACCOUNT_DELETE,
|
||||
];
|
||||
private static array $accounts;
|
||||
private AccountAcl $accountAcl;
|
||||
private static array $accounts;
|
||||
private Acl $acl;
|
||||
private UserToUserGroupServiceInterface|MockObject $userToUserGroupService;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
@@ -192,8 +197,7 @@ class AccountAclTest extends UnitaryTestCase
|
||||
self::$faker->numberBetween(1, 4),
|
||||
self::$faker->randomNumber(),
|
||||
self::$faker->randomNumber(),
|
||||
1,
|
||||
0
|
||||
true
|
||||
),
|
||||
$this->getExampleAclForAdmin()
|
||||
);
|
||||
@@ -210,10 +214,16 @@ class AccountAclTest extends UnitaryTestCase
|
||||
AccountAclDto $accountAclDto,
|
||||
AccountPermission $example
|
||||
): void {
|
||||
$accountAcl = new AccountAcl(
|
||||
$this->application,
|
||||
$this->acl,
|
||||
$this->userToUserGroupService
|
||||
);
|
||||
|
||||
foreach (self::ACTIONS as $action) {
|
||||
$example->setActionId($action);
|
||||
|
||||
$aclUnderTest = $this->accountAcl->getAcl($action, $accountAclDto);
|
||||
$aclUnderTest = $accountAcl->getAcl($action, $accountAclDto);
|
||||
|
||||
$this->assertTrue($aclUnderTest->isCompiledAccountAccess());
|
||||
$this->assertTrue($aclUnderTest->isCompiledShowAccess());
|
||||
@@ -321,12 +331,18 @@ class AccountAclTest extends UnitaryTestCase
|
||||
bool $isAdminApp = false,
|
||||
bool $isAdminAcc = false
|
||||
): AccountAclDto {
|
||||
$this->context
|
||||
->getUserData()
|
||||
->setId($userId)
|
||||
->setUserGroupId($groupId)
|
||||
->setIsAdminApp($isAdminApp)
|
||||
->setIsAdminAcc($isAdminAcc);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
new User(
|
||||
[
|
||||
'id' => $userId,
|
||||
'userGroupId' => $groupId,
|
||||
'isAdminApp' => $isAdminApp,
|
||||
'isAdminAcc' => $isAdminAcc
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return new AccountAclDto(
|
||||
$accountId,
|
||||
@@ -481,7 +497,6 @@ class AccountAclTest extends UnitaryTestCase
|
||||
*/
|
||||
#[Group('acl:admin')]
|
||||
#[DataProvider('accountPropertiesProvider')]
|
||||
|
||||
public function testEditPass(
|
||||
int $accountId,
|
||||
int $userId,
|
||||
@@ -674,6 +689,12 @@ class AccountAclTest extends UnitaryTestCase
|
||||
$fileCache = $this->createMock(FileCacheService::class);
|
||||
$actions = $this->createMock(ActionsInterface::class);
|
||||
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['lastUpdate' => $dto->getDateEdit() + 10])
|
||||
)
|
||||
);
|
||||
|
||||
$accountAclService = new AccountAcl(
|
||||
$this->application,
|
||||
new Acl($this->context, $this->application->getEventDispatcher(), $actions),
|
||||
@@ -681,8 +702,6 @@ class AccountAclTest extends UnitaryTestCase
|
||||
$fileCache
|
||||
);
|
||||
|
||||
$this->context->getUserData()->setLastUpdate($dto->getDateEdit() + 10);
|
||||
|
||||
$acl = new AccountPermission(self::$faker->randomNumber());
|
||||
$acl->setTime($dto->getDateEdit() + 10);
|
||||
|
||||
@@ -824,20 +843,14 @@ class AccountAclTest extends UnitaryTestCase
|
||||
|
||||
$actions = $this->createMock(ActionsInterface::class);
|
||||
|
||||
$acl = new Acl($this->context, $this->application->getEventDispatcher(), $actions);
|
||||
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
|
||||
$userToUserGroupService->method('getGroupsForUser')
|
||||
->willReturnMap([
|
||||
[1, [new Simple(['userGroupId' => 2])]],
|
||||
[2, [new Simple(['userGroupId' => 1])]],
|
||||
[3, [new Simple(['userGroupId' => 2])]],
|
||||
[4, []],
|
||||
]);
|
||||
|
||||
$this->accountAcl = new AccountAcl(
|
||||
$this->application,
|
||||
$acl,
|
||||
$userToUserGroupService
|
||||
);
|
||||
$this->acl = new Acl($this->context, $this->application->getEventDispatcher(), $actions);
|
||||
$this->userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
|
||||
$this->userToUserGroupService->method('getGroupsForUser')
|
||||
->willReturnMap([
|
||||
[1, [new Simple(['userGroupId' => 2])]],
|
||||
[2, [new Simple(['userGroupId' => 1])]],
|
||||
[3, [new Simple(['userGroupId' => 2])]],
|
||||
[4, []],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -31,6 +31,8 @@ use PHPUnit\Framework\Constraint\Callback;
|
||||
use PHPUnit\Framework\MockObject\Exception;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\Domain\Account\Services\Builders\AccountFilter;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
/**
|
||||
@@ -149,7 +151,11 @@ class AccountFilterUserTest extends UnitaryTestCase
|
||||
|
||||
public function testBuildFilterWithGlobalSearchForAdminAcc()
|
||||
{
|
||||
$this->context->getUserData()->setIsAdminAcc(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminAcc' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->setExpectationForGlobalSearch('Account');
|
||||
|
||||
@@ -183,7 +189,11 @@ class AccountFilterUserTest extends UnitaryTestCase
|
||||
|
||||
public function testBuildFilterWithGlobalSearchForAdminApp()
|
||||
{
|
||||
$this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminApp' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->setExpectationForGlobalSearch('Account');
|
||||
|
||||
@@ -209,7 +219,11 @@ class AccountFilterUserTest extends UnitaryTestCase
|
||||
|
||||
public function testBuildFilterHistoryWithGlobalSearchForAdminAcc()
|
||||
{
|
||||
$this->context->getUserData()->setIsAdminAcc(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminAcc' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->setExpectationForGlobalSearch('AccountHistory');
|
||||
|
||||
@@ -218,7 +232,11 @@ class AccountFilterUserTest extends UnitaryTestCase
|
||||
|
||||
public function testBuildFilterHistoryWithGlobalSearchForAdminApp()
|
||||
{
|
||||
$this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminApp' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->setExpectationForGlobalSearch('AccountHistory');
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Constraint\Callback;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\DataModel\ItemPreset\AccountPrivate;
|
||||
use SP\DataModel\ProfileData;
|
||||
use SP\Domain\Account\Dtos\AccountHistoryCreateDto;
|
||||
use SP\Domain\Account\Dtos\AccountUpdateBulkDto;
|
||||
use SP\Domain\Account\Dtos\AccountUpdateDto;
|
||||
@@ -51,10 +52,12 @@ use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\ItemPreset\Models\ItemPreset;
|
||||
use SP\Domain\ItemPreset\Ports\ItemPresetInterface;
|
||||
use SP\Domain\ItemPreset\Ports\ItemPresetService;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Infrastructure\Database\QueryResult;
|
||||
use SPT\Generators\AccountDataGenerator;
|
||||
use SPT\Generators\ItemSearchDataGenerator;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\Stubs\AccountRepositoryStub;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
@@ -86,7 +89,11 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$accountUpdateDto = $accountDataGenerator->buildAccountUpdateDto();
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminApp' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
->with('masterPwd')->willReturn(self::$faker->password);
|
||||
@@ -115,7 +122,11 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$accountUpdateDto = $accountDataGenerator->buildAccountUpdateDto();
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()->buildUserData()->mutate(['isAdminApp' => false])
|
||||
)
|
||||
);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
->with('masterPwd')->willReturn(self::$faker->password);
|
||||
@@ -144,8 +155,14 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$accountUpdateDto = $accountDataGenerator->buildAccountUpdateDto();
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->getUserData()->setIsAdminAcc(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isAdminApp' => false, 'isAdminAcc' => true])
|
||||
)
|
||||
);
|
||||
|
||||
$this->context->getUserProfile()->setAccPermission(false);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
@@ -175,8 +192,14 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$accountUpdateDto = $accountDataGenerator->buildAccountUpdateDto();
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->getUserData()->setIsAdminAcc(false);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isAdminApp' => false, 'isAdminAcc' => false])
|
||||
)
|
||||
);
|
||||
|
||||
$this->context->getUserProfile()->setAccPermission(true);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
@@ -216,10 +239,20 @@ class AccountTest extends UnitaryTestCase
|
||||
'data' => serialize(new AccountPrivate(true, true)),
|
||||
]);
|
||||
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setIsAdminApp(true);
|
||||
$userData->setId($accountUpdateDto->getUserId());
|
||||
$userData->setUserGroupId($accountUpdateDto->getUserGroupId());
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'id' => $accountUpdateDto->getUserId(),
|
||||
'userGroupId' => $accountUpdateDto->getUserGroupId(),
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
->with('masterPwd')->willReturn(self::$faker->password);
|
||||
@@ -283,10 +316,20 @@ class AccountTest extends UnitaryTestCase
|
||||
'data' => serialize(new AccountPrivate(true, true)),
|
||||
]);
|
||||
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setIsAdminApp(true);
|
||||
$userData->setId($accountUpdateDto->getUserId());
|
||||
$userData->setUserGroupId($accountUpdateDto->getUserGroupId());
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'id' => $accountUpdateDto->getUserId(),
|
||||
'userGroupId' => $accountUpdateDto->getUserGroupId(),
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->configService->expects(self::once())->method('getByParam')
|
||||
->with('masterPwd')->willReturn(self::$faker->password);
|
||||
@@ -513,7 +556,18 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountsId = range(0, 4);
|
||||
$accountUpdateBulkDto = new AccountUpdateBulkDto($accountsId, $accounts);
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$consecutive = array_merge($accountsId, $accountsId);
|
||||
sort($consecutive);
|
||||
@@ -545,7 +599,18 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountsId = range(0, 4);
|
||||
$accountUpdateBulkDto = new AccountUpdateBulkDto($accountsId, $accounts);
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => false,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->accountRepository->expects(self::exactly(count($accountsId)))->method('getById')
|
||||
->with(...self::withConsecutive(...array_map(fn($v) => [$v], $accountsId)))
|
||||
@@ -574,9 +639,20 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountsId = range(0, 4);
|
||||
$accountUpdateBulkDto = new AccountUpdateBulkDto($accountsId, $accounts);
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->getUserData()->setIsAdminAcc(true);
|
||||
$this->context->getUserProfile()->setAccPermission(false);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->context->setUserProfile(new ProfileData(['accPermission' => false]));
|
||||
|
||||
$consecutive = array_merge($accountsId, $accountsId);
|
||||
sort($consecutive);
|
||||
@@ -608,9 +684,20 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountsId = range(0, 4);
|
||||
$accountUpdateBulkDto = new AccountUpdateBulkDto($accountsId, $accounts);
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(false);
|
||||
$this->context->getUserData()->setIsAdminAcc(false);
|
||||
$this->context->getUserProfile()->setAccPermission(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => false,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->context->setUserProfile(new ProfileData(['accPermission' => true]));
|
||||
|
||||
$consecutive = array_merge($accountsId, $accountsId);
|
||||
sort($consecutive);
|
||||
@@ -623,8 +710,10 @@ class AccountTest extends UnitaryTestCase
|
||||
$this->accountItemsService->expects(self::exactly(count($accountsId)))->method('updateItems')
|
||||
->with(
|
||||
...self::withConsecutive(
|
||||
...array_map(fn($v) => [$v, true, $accounts[$v]],
|
||||
$accountsId)
|
||||
...array_map(
|
||||
fn($v) => [$v, true, $accounts[$v]],
|
||||
$accountsId
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -669,8 +758,6 @@ class AccountTest extends UnitaryTestCase
|
||||
$this->accountHistoryService->expects(self::once())->method('create')
|
||||
->with($accountHistoryCreateDto);
|
||||
|
||||
$queryResult = new QueryResult();
|
||||
|
||||
$this->accountRepository->expects(self::once())->method('delete')
|
||||
->with($id)
|
||||
->willReturn(new QueryResult(null, 1));
|
||||
@@ -980,7 +1067,18 @@ class AccountTest extends UnitaryTestCase
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$accountCreateDto = $accountDataGenerator->buildAccountCreateDto();
|
||||
|
||||
$this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$encryptedPassword = new EncryptedPassword(self::$faker->password, self::$faker->password);
|
||||
|
||||
@@ -1012,10 +1110,24 @@ class AccountTest extends UnitaryTestCase
|
||||
$id = self::$faker->randomNumber();
|
||||
$accountDataGenerator = AccountDataGenerator::factory();
|
||||
$userData = $this->context->getUserData();
|
||||
$accountCreateDto = $accountDataGenerator->buildAccountCreateDto()->withUserId($userData->getId())
|
||||
$accountCreateDto = $accountDataGenerator->buildAccountCreateDto()
|
||||
->withUserId($userData->getId())
|
||||
->withUserGroupId($userData->getUserGroupId());
|
||||
|
||||
$userData->setIsAdminApp(false);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'id' => $userData->getId(),
|
||||
'userGroupId' => $userData->getUserGroupId(),
|
||||
'isAdminApp' => false,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$encryptedPassword = new EncryptedPassword(self::$faker->password, self::$faker->password);
|
||||
|
||||
@@ -1058,9 +1170,21 @@ class AccountTest extends UnitaryTestCase
|
||||
'data' => serialize(new AccountPrivate(true, true)),
|
||||
]);
|
||||
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setIsAdminApp(true);
|
||||
$userData->setId($accountCreateDto->getUserId());
|
||||
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'id' => $accountCreateDto->getUserId(),
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$encryptedPassword = new EncryptedPassword(self::$faker->password, self::$faker->password);
|
||||
|
||||
@@ -1113,9 +1237,19 @@ class AccountTest extends UnitaryTestCase
|
||||
'data' => serialize(new AccountPrivate(true, true)),
|
||||
]);
|
||||
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setIsAdminApp(true);
|
||||
$userData->setUserGroupId($accountCreateDto->getUserGroupId());
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'userGroupId' => $accountCreateDto->getUserGroupId(),
|
||||
'isAdminApp' => true,
|
||||
'isAdminAcc' => false
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$encryptedPassword = new EncryptedPassword(self::$faker->password, self::$faker->password);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ use Defuse\Crypto\KeyProtectedByPassword;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMException;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Constraint\Callback;
|
||||
use PHPUnit\Framework\MockObject\Exception;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
@@ -46,10 +47,11 @@ use SP\Domain\Export\Ports\XmlClientExportService;
|
||||
use SP\Domain\Export\Ports\XmlTagExportService;
|
||||
use SP\Domain\Export\Services\XmlExport;
|
||||
use SP\Domain\File\Ports\DirectoryHandlerService;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Infrastructure\File\FileException;
|
||||
use SP\Util\VersionUtil;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
/**
|
||||
* Class XmlExportTest
|
||||
@@ -78,10 +80,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExport()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -216,10 +226,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithCheckDirectoryException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -240,10 +258,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithExportCategoryException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -274,10 +300,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithExportClientException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -315,10 +349,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithExportTagException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -361,10 +403,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithExportAccountException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
@@ -411,10 +461,18 @@ class XmlExportTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testExportWithCryptException()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setLogin('test_user');
|
||||
$userData->setUserGroupName('test_group');
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'login' => 'test_user',
|
||||
'userGroup.name' => 'test_group',
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$exportPath = $this->createMock(DirectoryHandlerService::class);
|
||||
$exportPath->expects(self::once())
|
||||
|
||||
@@ -34,9 +34,11 @@ use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Notification\Models\Notification as NotificationModel;
|
||||
use SP\Domain\Notification\Ports\NotificationRepository;
|
||||
use SP\Domain\Notification\Services\Notification;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Infrastructure\Database\QueryResult;
|
||||
use SPT\Generators\NotificationDataGenerator;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
/**
|
||||
@@ -84,15 +86,24 @@ class NotificationTest extends UnitaryTestCase
|
||||
|
||||
public function testSearchWithAdmin()
|
||||
{
|
||||
$userData = $this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData($userData);
|
||||
$userDataDto = new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$this->context->setUserData($userDataDto);
|
||||
|
||||
$itemSearchData = new ItemSearchData();
|
||||
|
||||
$this->notificationRepository
|
||||
->expects($this->once())
|
||||
->method('searchForAdmin')
|
||||
->with($itemSearchData, $userData->getId());
|
||||
->with($itemSearchData, $userDataDto->getId());
|
||||
|
||||
$this->notification->search($itemSearchData);
|
||||
}
|
||||
@@ -151,8 +162,16 @@ class NotificationTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testGetAllActiveForCurrentUserWithAdmin()
|
||||
{
|
||||
$userData = $this->context->getUserData()->setIsAdminApp(true);
|
||||
$this->context->setUserData($userData);
|
||||
$userDataDto = new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
]
|
||||
)
|
||||
);
|
||||
$this->context->setUserData($userDataDto);
|
||||
|
||||
$queryResult = $this->createMock(QueryResult::class);
|
||||
$queryResult->expects($this->once())
|
||||
@@ -163,7 +182,7 @@ class NotificationTest extends UnitaryTestCase
|
||||
$this->notificationRepository
|
||||
->expects($this->once())
|
||||
->method('getAllActiveForAdmin')
|
||||
->with($userData->getId())
|
||||
->with($userDataDto->getId())
|
||||
->willReturn($queryResult);
|
||||
|
||||
$out = $this->notification->getAllActiveForCurrentUser();
|
||||
|
||||
761
tests/SPT/Domain/User/Services/UserMasterPassTest.php
Normal file
761
tests/SPT/Domain/User/Services/UserMasterPassTest.php
Normal file
@@ -0,0 +1,761 @@
|
||||
<?php
|
||||
/*
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass 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.
|
||||
*
|
||||
* sysPass 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 sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SPT\Domain\User\Services;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use RuntimeException;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Common\Services\ServiceException;
|
||||
use SP\Domain\Config\Ports\ConfigService;
|
||||
use SP\Domain\Core\Crypt\CryptInterface;
|
||||
use SP\Domain\Core\Exceptions\CryptException;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Ports\UserRepository;
|
||||
use SP\Domain\User\Services\UserMasterPass;
|
||||
use SP\Domain\User\Services\UserMasterPassStatus;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
use SPT\UnitaryTestCase;
|
||||
|
||||
/**
|
||||
* Class UserMasterPassTest
|
||||
*/
|
||||
#[Group('unitary')]
|
||||
class UserMasterPassTest extends UnitaryTestCase
|
||||
{
|
||||
|
||||
private MockObject|UserRepository $userRepository;
|
||||
private MockObject|ConfigService $configService;
|
||||
private MockObject|CryptInterface $crypt;
|
||||
private UserMasterPass $userMasterPass;
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoad()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with($user->getMPass(), $user->getMKey(), $key)
|
||||
->willReturn('a_master_pass');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
$this->assertEquals($userDataDto->getMPass(), $out->getCryptMasterPass());
|
||||
$this->assertEquals($userDataDto->getMKey(), $out->getCryptSecuredKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithUserPass()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = 'a_password' .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with($user->getMPass(), $user->getMKey(), $key)
|
||||
->willReturn('a_master_pass');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto, 'a_password');
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
$this->assertEquals($userDataDto->getMPass(), $out->getCryptMasterPass());
|
||||
$this->assertEquals($userDataDto->getMKey(), $out->getCryptSecuredKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithNotSet()
|
||||
{
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password());
|
||||
|
||||
$this->configService
|
||||
->expects($this->never())
|
||||
->method('getByParam');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::NotSet, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithNotSetAndEmptyPass()
|
||||
{
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName());
|
||||
|
||||
$this->configService
|
||||
->expects($this->never())
|
||||
->method('getByParam');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::NotSet, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithNotSetAndEmptyUser()
|
||||
{
|
||||
$userLoginDto = new UserLoginDto();
|
||||
|
||||
$this->configService
|
||||
->expects($this->never())
|
||||
->method('getByParam');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::NotSet, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithNotSetAndNullHash()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('getByParam')
|
||||
->willReturn(null);
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::NotSet, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithChanged()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 0]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Changed, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithCheckOld()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => true, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), null, $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('decrypt');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::CheckOld, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithCryptException()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->willThrowException(CryptException::error('test'));
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::CheckOld, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithInvalid()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with($user->getMPass(), $user->getMKey(), $key)
|
||||
->willReturn('a_pass');
|
||||
|
||||
$out = $this->userMasterPass->load($userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Invalid, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testLoadWithException()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->willThrowException(new RuntimeException('test'));
|
||||
|
||||
$this->expectException(ServiceException::class);
|
||||
$this->expectExceptionMessage('test');
|
||||
|
||||
$this->userMasterPass->load($userLoginDto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testUpdateFromOldPass()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(3))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass'], ['masterPwd']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5', Hash::hashKey('a_master_pass'));
|
||||
|
||||
$oldKey = 'an_old_user_pass' .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with($user->getMPass(), $user->getMKey(), $oldKey)
|
||||
->willReturn('a_master_pass');
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secure_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secure_key', $key)
|
||||
->willReturn('encrypted');
|
||||
|
||||
$this->userRepository
|
||||
->expects($this->once())
|
||||
->method('updateMasterPassById')
|
||||
->with($userDataDto->getId(), 'encrypted', 'a_secure_key');
|
||||
|
||||
$out = $this->userMasterPass->updateFromOldPass('an_old_user_pass', $userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('encrypted', $out->getCryptMasterPass());
|
||||
$this->assertEquals('a_secure_key', $out->getCryptSecuredKey());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testUpdateFromOldPassWithInvalid()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->exactly(2))
|
||||
->method('getByParam')
|
||||
->with(...self::withConsecutive(['masterPwd'], ['lastupdatempass']))
|
||||
->willReturn(Hash::hashKey('a_master_pass'), '5');
|
||||
|
||||
$oldKey = 'an_old_user_pass' .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('decrypt')
|
||||
->with($user->getMPass(), $user->getMKey(), $oldKey)
|
||||
->willReturn('another_master_pass');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('makeSecuredKey');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('encrypt');
|
||||
|
||||
$this->userRepository
|
||||
->expects($this->never())
|
||||
->method('updateMasterPassById');
|
||||
|
||||
$out = $this->userMasterPass->updateFromOldPass('an_old_user_pass', $userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Invalid, $out->getUserMasterPassStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testUpdateOnLogin()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('getByParam')
|
||||
->with('masterPwd')
|
||||
->willReturn(Hash::hashKey('a_master_pass'));
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secure_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secure_key', $key)
|
||||
->willReturn('encrypted');
|
||||
|
||||
$this->userRepository
|
||||
->expects($this->once())
|
||||
->method('updateMasterPassById')
|
||||
->with($userDataDto->getId(), 'encrypted', 'a_secure_key');
|
||||
|
||||
$out = $this->userMasterPass->updateOnLogin('a_master_pass', $userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('encrypted', $out->getCryptMasterPass());
|
||||
$this->assertEquals('a_secure_key', $out->getCryptSecuredKey());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testUpdateOnLoginWithSaveHash()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('getByParam')
|
||||
->with('masterPwd')
|
||||
->willReturn(null);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('save')
|
||||
->with(
|
||||
'masterPwd',
|
||||
self::callback(static function (string $hash) {
|
||||
return Hash::checkHashKey('a_master_pass', $hash);
|
||||
})
|
||||
);
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secure_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secure_key', $key)
|
||||
->willReturn('encrypted');
|
||||
|
||||
$this->userRepository
|
||||
->expects($this->once())
|
||||
->method('updateMasterPassById')
|
||||
->with($userDataDto->getId(), 'encrypted', 'a_secure_key');
|
||||
|
||||
$out = $this->userMasterPass->updateOnLogin('a_master_pass', $userLoginDto);
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('encrypted', $out->getCryptMasterPass());
|
||||
$this->assertEquals('a_secure_key', $out->getCryptSecuredKey());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testUpdateOnLoginWithException()
|
||||
{
|
||||
$user = UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(['isChangedPass' => false, 'lastUpdateMPass' => 10]);
|
||||
|
||||
$userDataDto = new UserDataDto($user);
|
||||
$userLoginDto = new UserLoginDto(self::$faker->userName(), self::$faker->password(), $userDataDto);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('getByParam')
|
||||
->with('masterPwd')
|
||||
->willReturn(null);
|
||||
|
||||
$this->configService
|
||||
->expects($this->once())
|
||||
->method('save')
|
||||
->with(
|
||||
'masterPwd',
|
||||
self::callback(static function (string $hash) {
|
||||
return Hash::checkHashKey('a_master_pass', $hash);
|
||||
})
|
||||
);
|
||||
|
||||
$key = $userLoginDto->getLoginPass() .
|
||||
$userLoginDto->getLoginUser() .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secure_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secure_key', $key)
|
||||
->willReturn('encrypted');
|
||||
|
||||
$this->userRepository
|
||||
->expects($this->once())
|
||||
->method('updateMasterPassById')
|
||||
->willThrowException(new RuntimeException('test'));
|
||||
|
||||
$this->expectException(ServiceException::class);
|
||||
$this->expectExceptionMessage('test');
|
||||
|
||||
$this->userMasterPass->updateOnLogin('a_master_pass', $userLoginDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$key = 'a_password' .
|
||||
'a_login' .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secure_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secure_key', $key)
|
||||
->willReturn('encrypted');
|
||||
|
||||
$out = $this->userMasterPass->create('a_master_pass', 'a_login', 'a_password');
|
||||
|
||||
$this->assertEquals(UserMasterPassStatus::Ok, $out->getUserMasterPassStatus());
|
||||
$this->assertEquals('encrypted', $out->getCryptMasterPass());
|
||||
$this->assertEquals('a_secure_key', $out->getCryptSecuredKey());
|
||||
$this->assertEquals('a_master_pass', $out->getClearMasterPass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testCreateWithLongKey()
|
||||
{
|
||||
$key = 'a_password' .
|
||||
'a_login' .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$longKey = str_repeat('a', 1001);
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn($longKey);
|
||||
|
||||
$this->crypt
|
||||
->expects($this->never())
|
||||
->method('encrypt');
|
||||
|
||||
$this->expectException(ServiceException::class);
|
||||
$this->expectExceptionMessage('Internal error');
|
||||
|
||||
$this->userMasterPass->create('a_master_pass', 'a_login', 'a_password');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testCreateWithLongMasterPass()
|
||||
{
|
||||
$key = 'a_password' .
|
||||
'a_login' .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secured_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secured_key', $key)
|
||||
->willReturn(str_repeat('a', 1001));
|
||||
|
||||
$this->expectException(ServiceException::class);
|
||||
$this->expectExceptionMessage('Internal error');
|
||||
|
||||
$this->userMasterPass->create('a_master_pass', 'a_login', 'a_password');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function testCreateWithException()
|
||||
{
|
||||
$key = 'a_password' .
|
||||
'a_login' .
|
||||
$this->config->getConfigData()->getPasswordSalt();
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('makeSecuredKey')
|
||||
->with($key)
|
||||
->willReturn('a_secured_key');
|
||||
|
||||
$this->crypt
|
||||
->expects($this->once())
|
||||
->method('encrypt')
|
||||
->with('a_master_pass', 'a_secured_key', $key)
|
||||
->willThrowException(CryptException::error('test'));
|
||||
|
||||
$this->expectException(ServiceException::class);
|
||||
$this->expectExceptionMessage('test');
|
||||
|
||||
$this->userMasterPass->create('a_master_pass', 'a_login', 'a_password');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->userRepository = $this->createMock(UserRepository::class);
|
||||
$this->configService = $this->createMock(ConfigService::class);
|
||||
$this->crypt = $this->createMock(CryptInterface::class);
|
||||
|
||||
$this->userMasterPass = new UserMasterPass(
|
||||
$this->application,
|
||||
$this->userRepository,
|
||||
$this->configService,
|
||||
$this->crypt
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,6 @@ final class ConfigDataGenerator extends DataGenerator
|
||||
{
|
||||
return new ConfigData([
|
||||
ConfigDataInterface::PASSWORD_SALT => $this->faker->sha1(),
|
||||
]);
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ use SP\Domain\Common\Models\Simple as SimpleModel;
|
||||
use SP\Domain\Core\Exceptions\ConstraintException;
|
||||
use SP\Domain\Core\Exceptions\QueryException;
|
||||
use SP\Domain\Core\Exceptions\SPException;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Models\User as UserModel;
|
||||
use SP\Infrastructure\Common\Repositories\DuplicatedItemException;
|
||||
use SP\Infrastructure\Database\DatabaseInterface;
|
||||
@@ -599,10 +600,17 @@ class UserTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testSearchWithAdmin()
|
||||
{
|
||||
$userData = $this->context->getUserData();
|
||||
$userData->setIsAdminApp(true);
|
||||
|
||||
$this->context->setUserData($userData);
|
||||
$this->context->setUserData(
|
||||
new UserDataDto(
|
||||
UserDataGenerator::factory()
|
||||
->buildUserData()
|
||||
->mutate(
|
||||
[
|
||||
'isAdminApp' => true,
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$item = new ItemSearchData(self::$faker->name);
|
||||
|
||||
@@ -673,11 +681,12 @@ class UserTest extends UnitaryTestCase
|
||||
$query = $arg->getQuery();
|
||||
$params = $query->getBindValues();
|
||||
|
||||
return count($params) === 4
|
||||
return count($params) === 5
|
||||
&& $params['id'] === $user->getId()
|
||||
&& $params['pass'] === $user->getPass()
|
||||
&& $params['isChangePass'] === $user->isChangePass()
|
||||
&& $params['isChangedPass'] === $user->isChangedPass()
|
||||
&& $params['isMigrate'] === $user->isMigrate()
|
||||
&& is_a($query, UpdateInterface::class)
|
||||
&& !empty($query->getStatement());
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -26,7 +26,7 @@ namespace SPT\Providers\Auth;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\Exception;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Auth\Services\AuthException;
|
||||
use SP\Providers\Auth\AuthInterface;
|
||||
use SP\Providers\Auth\AuthProvider;
|
||||
@@ -66,7 +66,7 @@ class AuthProviderTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testDoAuth()
|
||||
{
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
$userLoginData->setLoginPass(self::$faker->password);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -26,7 +26,7 @@ namespace SPT\Providers\Auth\Browser;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
use SP\Domain\Http\RequestInterface;
|
||||
use SP\Providers\Auth\Browser\BrowserAuth;
|
||||
@@ -83,7 +83,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
$user = self::$faker->userName;
|
||||
$pass = self::$faker->password;
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -125,7 +125,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
->with(...$this->withConsecutive(['PHP_AUTH_USER'], ['PHP_AUTH_PW']))
|
||||
->willReturn($user, $pass);
|
||||
|
||||
$out = $this->browserAuth->authenticate(new UserLoginData());
|
||||
$out = $this->browserAuth->authenticate(new UserLoginDto());
|
||||
|
||||
self::assertInstanceOf(BrowserAuthData::class, $out);
|
||||
self::assertTrue($out->isOk());
|
||||
@@ -146,7 +146,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
->with(...$this->withConsecutive(['PHP_AUTH_USER'], ['REMOTE_USER'], ['PHP_AUTH_PW']))
|
||||
->willReturn('', '', '', $pass);
|
||||
|
||||
$out = $this->browserAuth->authenticate(new UserLoginData());
|
||||
$out = $this->browserAuth->authenticate(new UserLoginDto());
|
||||
|
||||
self::assertInstanceOf(BrowserAuthData::class, $out);
|
||||
self::assertFalse($out->isOk());
|
||||
@@ -167,7 +167,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
->with(...$this->withConsecutive(['PHP_AUTH_USER'], ['PHP_AUTH_PW']))
|
||||
->willReturn($user, '');
|
||||
|
||||
$out = $this->browserAuth->authenticate(new UserLoginData());
|
||||
$out = $this->browserAuth->authenticate(new UserLoginDto());
|
||||
|
||||
self::assertInstanceOf(BrowserAuthData::class, $out);
|
||||
self::assertFalse($out->isOk());
|
||||
@@ -188,7 +188,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
->with('PHP_AUTH_USER')
|
||||
->willReturn($user);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
|
||||
$out = $this->browserAuth->authenticate($userLoginData);
|
||||
@@ -212,7 +212,7 @@ class BrowserAuthTest extends UnitaryTestCase
|
||||
->with('PHP_AUTH_USER')
|
||||
->willReturn($user);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
|
||||
$out = $this->browserAuth->authenticate($userLoginData);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
|
||||
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
@@ -27,9 +27,9 @@ namespace SPT\Providers\Auth\Database;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\User\Ports\UserPassServiceInterface;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\User\Ports\UserServiceInterface;
|
||||
use SP\Domain\User\Services\UserPassService;
|
||||
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
|
||||
use SP\Providers\Auth\Database\DatabaseAuth;
|
||||
use SPT\Generators\UserDataGenerator;
|
||||
@@ -43,9 +43,9 @@ use SPT\UnitaryTestCase;
|
||||
class DatabaseAuthTest extends UnitaryTestCase
|
||||
{
|
||||
|
||||
private UserServiceInterface|MockObject $userService;
|
||||
private MockObject|UserPassServiceInterface $userPassService;
|
||||
private DatabaseAuth $databaseAuth;
|
||||
private UserServiceInterface|MockObject $userService;
|
||||
private MockObject|UserPassService $userPassService;
|
||||
private DatabaseAuth $databaseAuth;
|
||||
|
||||
public function testAuthenticate()
|
||||
{
|
||||
@@ -61,7 +61,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->with($user)
|
||||
->willReturn($userData);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -79,7 +79,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->with($user)
|
||||
->willThrowException(new NoSuchItemException('User does not exist'));
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -99,7 +99,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->with($user)
|
||||
->willReturn($userData);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -132,7 +132,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->method('migrateUserPassById')
|
||||
->with($userData->getId(), $pass);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -167,7 +167,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->method('migrateUserPassById')
|
||||
->with($userData->getId(), $pass);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -202,7 +202,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->method('migrateUserPassById')
|
||||
->with($userData->getId(), $pass);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -236,7 +236,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
->method('migrateUserPassById')
|
||||
->with($userData->getId(), $pass);
|
||||
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser($user);
|
||||
$userLoginData->setLoginPass($pass);
|
||||
|
||||
@@ -253,7 +253,7 @@ class DatabaseAuthTest extends UnitaryTestCase
|
||||
parent::setUp();
|
||||
|
||||
$this->userService = $this->createMock(UserServiceInterface::class);
|
||||
$this->userPassService = $this->createMock(UserPassServiceInterface::class);
|
||||
$this->userPassService = $this->createMock(UserPassService::class);
|
||||
|
||||
$this->databaseAuth = new DatabaseAuth($this->userService, $this->userPassService);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ use PHPUnit\Framework\Constraint\Callback;
|
||||
use PHPUnit\Framework\MockObject\Exception;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\MockObject\Rule\InvokedCount;
|
||||
use SP\DataModel\UserLoginData;
|
||||
use SP\Domain\Auth\Dtos\UserLoginDto;
|
||||
use SP\Domain\Auth\Ports\LdapActionsService;
|
||||
use SP\Domain\Auth\Ports\LdapService;
|
||||
use SP\Domain\Config\Ports\ConfigDataInterface;
|
||||
@@ -58,7 +58,7 @@ class LdapAuthTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testAuthenticate()
|
||||
{
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
$userLoginData->setLoginPass(self::$faker->password);
|
||||
|
||||
@@ -140,7 +140,7 @@ class LdapAuthTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testAuthenticateWithExpireFail()
|
||||
{
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
$userLoginData->setLoginPass(self::$faker->password);
|
||||
|
||||
@@ -188,7 +188,7 @@ class LdapAuthTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testAuthenticateWithGroupFail()
|
||||
{
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
$userLoginData->setLoginPass(self::$faker->password);
|
||||
|
||||
@@ -236,7 +236,7 @@ class LdapAuthTest extends UnitaryTestCase
|
||||
*/
|
||||
public function testAuthenticateFailConnect()
|
||||
{
|
||||
$userLoginData = new UserLoginData();
|
||||
$userLoginData = new UserLoginDto();
|
||||
$userLoginData->setLoginUser(self::$faker->userName);
|
||||
$userLoginData->setLoginPass(self::$faker->password);
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ use SP\DataModel\ProfileData;
|
||||
use SP\Domain\Config\Ports\ConfigFileService;
|
||||
use SP\Domain\Core\Context\ContextInterface;
|
||||
use SP\Domain\Core\Events\EventDispatcherInterface;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Domain\User\Models\User;
|
||||
use SPT\Generators\ConfigDataGenerator;
|
||||
|
||||
/**
|
||||
@@ -95,17 +96,9 @@ abstract class UnitaryTestCase extends TestCase
|
||||
*/
|
||||
private function mockApplication(): Application
|
||||
{
|
||||
$userLogin = new UserLoginResponse();
|
||||
$userLogin
|
||||
->setLogin(self::$faker->userName)
|
||||
->setName(self::$faker->userName)
|
||||
->setId(self::$faker->randomNumber(2))
|
||||
->setUserGroupId(self::$faker->randomNumber(2))
|
||||
->setUserProfileId(self::$faker->randomNumber(2));
|
||||
|
||||
$this->context = new StatelessContext();
|
||||
$this->context->initialize();
|
||||
$this->context->setUserData($userLogin);
|
||||
$this->context->setUserData($this->getUserDataDto());
|
||||
$this->context->setUserProfile(new ProfileData());
|
||||
|
||||
return new Application(
|
||||
@@ -115,6 +108,24 @@ abstract class UnitaryTestCase extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserDataDto
|
||||
*/
|
||||
private function getUserDataDto(): UserDataDto
|
||||
{
|
||||
return new UserDataDto(
|
||||
new User(
|
||||
[
|
||||
'login' => self::$faker->userName,
|
||||
'name' => self::$faker->userName,
|
||||
'id' => self::$faker->randomNumber(2),
|
||||
'userGroupId' => self::$faker->randomNumber(2),
|
||||
'userProfileId' => self::$faker->randomNumber(2)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ use SP\Core\Context\ContextException;
|
||||
use SP\DataModel\ProfileData;
|
||||
use SP\Domain\Core\Context\ContextInterface;
|
||||
use SP\Domain\Core\Exceptions\FileNotFoundException;
|
||||
use SP\Domain\User\Services\UserLoginResponse;
|
||||
use SP\Domain\User\Dtos\UserDataDto;
|
||||
use SP\Infrastructure\Database\DatabaseConnectionData;
|
||||
use SP\Infrastructure\Database\DbStorageHandler;
|
||||
use SP\Infrastructure\Database\MysqlHandler;
|
||||
@@ -127,7 +127,7 @@ function setupContext(): Container
|
||||
|
||||
$context->setTrasientKey('_masterpass', '12345678900');
|
||||
|
||||
$userData = new UserLoginResponse();
|
||||
$userData = new UserDataDto();
|
||||
$userData->setId(1);
|
||||
$userData->setLogin('Admin');
|
||||
$userData->setUserGroupName('Admins');
|
||||
|
||||
Reference in New Issue
Block a user