Skip to content

Commit

Permalink
OXDEV-7728: Refactoring and tests for Password
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcelOxid committed Jun 3, 2024
1 parent 27c97e1 commit bb28ab8
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 22 deletions.
12 changes: 12 additions & 0 deletions src/Customer/Infrastructure/PasswordInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace OxidEsales\GraphQL\Storefront\Customer\Infrastructure;

use OxidEsales\Eshop\Application\Model\User;

interface PasswordInterface
{
public function sendPasswordForgotEmail(string $email): bool|int;

public function validatePassword(User $customer, string $newPassword, string $repeatPassword): void;
}
27 changes: 27 additions & 0 deletions src/Customer/Infrastructure/RepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace OxidEsales\GraphQL\Storefront\Customer\Infrastructure;

use OxidEsales\Eshop\Application\Model\User as EshopUserModel;
use OxidEsales\GraphQL\Storefront\Address\DataType\DeliveryAddress;
use OxidEsales\GraphQL\Storefront\Customer\DataType\Customer as CustomerDataType;
use OxidEsales\GraphQL\Storefront\Customer\Exception\CustomerNotFoundByUpdateId;

interface RepositoryInterface
{
/**
* @throws CustomerNotFoundByUpdateId
*/
public function createUser(EshopUserModel $user): CustomerDataType;

/**
* @return DeliveryAddress[]
*/
public function addresses(CustomerDataType $customer): array;

public function checkEmailExists(string $email): bool;

public function saveNewPasswordForCustomer(EshopUserModel $customer, string $newPassword): bool;

public function getCustomerByPasswordUpdateId(string $passwordUpdateId): EshopUserModel;
}
8 changes: 4 additions & 4 deletions src/Customer/Service/Customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
use OxidEsales\GraphQL\Storefront\Customer\Exception\InvalidEmail;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\Repository as CustomerRepository;
use OxidEsales\GraphQL\Storefront\Shared\Infrastructure\Repository;
use OxidEsales\GraphQL\Storefront\Shared\Service\Authorization;
use TheCodingMachine\GraphQLite\Security\AuthorizationServiceInterface;

final class Customer
final class Customer implements CustomerInterface
{
/** @var Repository */
private $repository;
Expand All @@ -37,15 +37,15 @@ final class Customer
/** @var Legacy */
private $legacyService;

/** @var Authorization */
/** @var AuthorizationServiceInterface */
private $authorizationService;

public function __construct(
Repository $repository,
CustomerRepository $customerRepository,
Authentication $authenticationService,
Legacy $legacyService,
Authorization $authorizationService
AuthorizationServiceInterface $authorizationService
) {
$this->repository = $repository;
$this->customerRepository = $customerRepository;
Expand Down
31 changes: 31 additions & 0 deletions src/Customer/Service/CustomerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace OxidEsales\GraphQL\Storefront\Customer\Service;

use DateTimeInterface;
use OxidEsales\GraphQL\Base\Exception\InvalidLogin;
use OxidEsales\GraphQL\Storefront\Customer\DataType\Customer as CustomerDataType;
use OxidEsales\GraphQL\Storefront\Customer\Exception\CustomerNotDeletable;
use OxidEsales\GraphQL\Storefront\Customer\Exception\CustomerNotFoundByUpdateId;

interface CustomerInterface
{
/**
* @throws InvalidLogin
* @throws CustomerNotFoundByUpdateId
*/
public function customer(string $id): CustomerDataType;

public function create(CustomerDataType $customer): CustomerDataType;

public function changeEmail(string $email): CustomerDataType;

public function changeBirthdate(DateTimeInterface $birthdate): CustomerDataType;

/**
* @throws CustomerNotDeletable
*/
public function deleteCustomer(): bool;

public function fetchCustomer(string $id): CustomerDataType;
}
31 changes: 13 additions & 18 deletions src/Customer/Service/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@

namespace OxidEsales\GraphQL\Storefront\Customer\Service;

use OxidEsales\GraphQL\Base\Service\Authentication;
use OxidEsales\GraphQL\Storefront\Customer\Exception\InvalidEmail;
use OxidEsales\GraphQL\Storefront\Customer\Exception\PasswordMismatch;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\Password as PasswordInfrastructure;
use OxidEsales\GraphQL\Storefront\Customer\Service\Customer as CustomerService;
use OxidEsales\GraphQL\Storefront\Shared\Infrastructure\Repository;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\PasswordInterface as PasswordInfrastructuredInterface;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\RepositoryInterface;
use TheCodingMachine\GraphQLite\Security\AuthenticationServiceInterface;

final class Password
final class Password implements PasswordInterface
{
public function __construct(
private readonly Repository $repository,
private readonly CustomerService $customerService,
private readonly Authentication $authenticationService,
private readonly PasswordInfrastructure $passwordInfrastructure,
private readonly RepositoryInterface $repository,
private readonly CustomerInterface $customerService,
private readonly AuthenticationServiceInterface $authenticationService,
private readonly PasswordInfrastructuredInterface $passwordInfrastructure,
) {
}

Expand All @@ -38,9 +37,7 @@ public function change(string $old, string $new): bool
throw PasswordMismatch::byOldPassword();
}

$customerModel->setPassword($new);

return $this->repository->saveModel($customerModel);
return $this->repository->saveNewPasswordForCustomer($customerModel, $new);
}

public function sendPasswordForgotEmail(string $email): bool
Expand All @@ -54,12 +51,10 @@ public function sendPasswordForgotEmail(string $email): bool
return $isSuccess;
}

public function resetPassword(string $updateId, string $newPassword, string $repeatPassword): bool
public function resetPasswordByUpdateId(string $updateId, string $newPassword, string $repeatPassword): bool
{
if (!$this->passwordInfrastructure->checkPassword($newPassword, $repeatPassword)) {
return false;
}

return $this->passwordInfrastructure->resetPassword($updateId, $newPassword);
$customer = $this->repository->getCustomerByPasswordUpdateId($updateId);
$this->passwordInfrastructure->validatePassword($customer, $newPassword, $repeatPassword);
return $this->repository->saveNewPasswordForCustomer($customer, $newPassword);
}
}
59 changes: 59 additions & 0 deletions tests/Unit/Customer/Service/PasswordServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\Storefront\Tests\Unit\Customer\Service;

use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\PasswordInterface as PasswordInfrastructureInterface;
use OxidEsales\GraphQL\Storefront\Customer\Infrastructure\RepositoryInterface as CustomerRepositoryInterface;
use OxidEsales\GraphQL\Storefront\Customer\Service\CustomerInterface;
use OxidEsales\GraphQL\Storefront\Customer\Service\Password as PasswordService;
use PHPUnit\Framework\TestCase;
use TheCodingMachine\GraphQLite\Security\AuthenticationServiceInterface;

/**
* @covers \OxidEsales\GraphQL\Storefront\Customer\Service\Password
*/
class PasswordServiceTest extends TestCase
{

public function testResetPasswordByUpdateId(): void
{
$customer = $this->createStub(User::class);
$password = 'password';
$passwordRepeated = 'password';

$customerRepository = $this->createMock(CustomerRepositoryInterface::class);
$customerRepository->expects($this->once())
->method('getCustomerByPasswordUpdateId')
->with('1234')
->willReturn($customer);
$customerRepository->expects($this->once())
->method('saveNewPasswordForCustomer')
->with($customer, $password);
$passwordInfrastructure = $this->createMock(PasswordInfrastructureInterface::class);
$passwordInfrastructure->expects($this->once())
->method('validatePassword')
->with(
$customer,
$password,
$passwordRepeated
);
$customerService = $this->createMock(CustomerInterface::class);
$authenticationService = $this->createMock(AuthenticationServiceInterface::class);
$passwordService = new PasswordService(
$customerRepository,
$customerService,
$authenticationService,
$passwordInfrastructure
);

$passwordService->resetPasswordByUpdateId('1234', $password, $passwordRepeated);
}
}

0 comments on commit bb28ab8

Please sign in to comment.