Skip to content

Commit

Permalink
User model refacto
Browse files Browse the repository at this point in the history
  • Loading branch information
mmarchois committed Jan 13, 2025
1 parent 18adba3 commit aec6f43
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
use App\Domain\User\Exception\UserAlreadyRegisteredException;
use App\Domain\User\Organization;
use App\Domain\User\OrganizationUser;
use App\Domain\User\PasswordUser;
use App\Domain\User\Repository\AccessRequestRepositoryInterface;
use App\Domain\User\Repository\OrganizationRepositoryInterface;
use App\Domain\User\Repository\OrganizationUserRepositoryInterface;
use App\Domain\User\Repository\PasswordUserRepositoryInterface;
use App\Domain\User\Repository\UserRepositoryInterface;
use App\Domain\User\User;

Expand All @@ -26,6 +28,7 @@ public function __construct(
private IdFactoryInterface $idFactory,
private AccessRequestRepositoryInterface $accessRequestRepository,
private UserRepositoryInterface $userRepository,
private PasswordUserRepositoryInterface $passwordUserRepository,
private OrganizationUserRepositoryInterface $organizationUserRepository,
private OrganizationRepositoryInterface $organizationRepository,
private DateUtilsInterface $dateUtils,
Expand Down Expand Up @@ -63,17 +66,23 @@ public function __invoke(ConvertAccessRequestToUserCommand $command): void

$user = (new User($this->idFactory->make()))
->setFullName($accessRequest->getFullName())
->setPassword($accessRequest->getPassword())
->setEmail($accessRequest->getEmail())
->setRoles([UserRolesEnum::ROLE_USER->value])
->setRegistrationDate($now);

$passwordUser = new PasswordUser(
uuid: $this->idFactory->make(),
password: $accessRequest->getPassword(),
user: $user,
);

$organizationUser = (new OrganizationUser($this->idFactory->make()))
->setUser($user)
->setOrganization($organization)
->setRoles($organizationRole);

$this->userRepository->add($user);
$this->passwordUserRepository->add($passwordUser);
$this->organizationUserRepository->add($organizationUser);
$this->accessRequestRepository->remove($accessRequest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use App\Domain\User\Exception\EmailAlreadyExistsException;
use App\Domain\User\Exception\UserAlreadyRegisteredException;
use App\Domain\User\OrganizationUser;
use App\Domain\User\PasswordUser;
use App\Domain\User\Repository\OrganizationUserRepositoryInterface;
use App\Domain\User\Repository\PasswordUserRepositoryInterface;
use App\Domain\User\Repository\UserRepositoryInterface;
use App\Domain\User\Specification\IsEmailAlreadyExists;
use App\Domain\User\Specification\IsUserAlreadyRegisteredInOrganization;
Expand All @@ -24,6 +26,7 @@ public function __construct(
private IdFactoryInterface $idFactory,
private OrganizationUserRepositoryInterface $organizationUserRepository,
private UserRepositoryInterface $userRepository,
private PasswordUserRepositoryInterface $passwordUserRepository,
private StringUtilsInterface $stringUtils,
private DateUtilsInterface $dateUtils,
private PasswordHasherInterface $passwordHasher,
Expand Down Expand Up @@ -66,11 +69,17 @@ public function __invoke(SaveOrganizationUserCommand $command): void
$user = (new User($this->idFactory->make()))
->setEmail($email)
->setFullName($command->fullName)
->setPassword($this->passwordHasher->hash($command->password))
->setRoles([UserRolesEnum::ROLE_USER->value])
->setRegistrationDate($this->dateUtils->getNow());

$passwordUser = new PasswordUser(
uuid: $this->idFactory->make(),
password: $this->passwordHasher->hash($command->password),
user: $user,
);

$this->userRepository->add($user);
$this->passwordUserRepository->add($passwordUser);
}

$this->organizationUserRepository->add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public function __invoke(SavePasswordCommand $command): void
{
$user = $command->user;
$password = $this->passwordHasher->hash($command->password);
$user->setPassword($password);
$user->getPasswordUser()->setPassword($password);
}
}
37 changes: 37 additions & 0 deletions src/Domain/User/PasswordUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace App\Domain\User;

class PasswordUser
{
public function __construct(
private string $uuid,
private string $password,
private User $user,
) {
}

public function getUuid(): string
{
return $this->uuid;
}

public function getPassword(): string
{
return $this->password;
}

public function setPassword(string $password): self
{
$this->password = $password;

return $this;
}

public function getUser(): User
{
return $this->user;
}
}
24 changes: 24 additions & 0 deletions src/Domain/User/ProConnectUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Domain\User;

class ProConnectUser
{
public function __construct(
private string $uuid,
private User $user,
) {
}

public function getUuid(): string
{
return $this->uuid;
}

public function getUser(): User
{
return $this->user;
}
}
12 changes: 12 additions & 0 deletions src/Domain/User/Repository/PasswordUserRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace App\Domain\User\Repository;

use App\Domain\User\PasswordUser;

interface PasswordUserRepositoryInterface
{
public function add(PasswordUser $passwordUser): PasswordUser;
}
25 changes: 12 additions & 13 deletions src/Domain/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ class User
{
private string $fullName;
private string $email;
private string $password;
private array $roles = [];
private \DateTimeInterface $registrationDate;
private ?\DateTimeInterface $lastActiveAt;
private ?PasswordUser $passwordUser = null;
private ?ProConnectUser $proConnectUser = null;

public function __construct(
private string $uuid,
Expand Down Expand Up @@ -47,18 +48,6 @@ public function setEmail(string $email): self
return $this;
}

public function getPassword(): string
{
return $this->password;
}

public function setPassword(string $password): self
{
$this->password = $password;

return $this;
}

public function getRoles(): array
{
return $this->roles;
Expand Down Expand Up @@ -95,6 +84,16 @@ public function setLastActiveAt(\DateTimeInterface $date): self
return $this;
}

public function getProConnectUser(): ?ProConnectUser
{
return $this->proConnectUser;
}

public function getPasswordUser(): ?PasswordUser
{
return $this->passwordUser;
}

public function __toString(): string
{
return \sprintf('%s (%s)', $this->fullName, $this->email);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function __invoke(Request $request): Response
if ($form->isSubmitted() && $form->isValid()) {
$this->commandBus->handle($command);
$symfonyUser = $this->authenticatedUser->getSymfonyUser();
$symfonyUser->setPassword($user->getPassword());
$symfonyUser->setPassword($user->getPasswordUser()->getPassword());

/** @var FlashBagAwareSessionInterface */
$session = $request->getSession();
Expand Down
25 changes: 22 additions & 3 deletions src/Infrastructure/Persistence/Doctrine/Fixtures/UserFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Infrastructure\Persistence\Doctrine\Fixtures;

use App\Domain\User\Enum\UserRolesEnum;
use App\Domain\User\PasswordUser;
use App\Domain\User\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
Expand All @@ -21,29 +22,47 @@ public function load(ObjectManager $manager): void
$mainOrgUser = (new User('0b507871-8b5e-4575-b297-a630310fc06e'))
->setFullName('Mathieu MARCHOIS')
->setEmail(self::MAIN_ORG_USER_EMAIL)
->setPassword(self::PASSWORD)
->setRoles([UserRolesEnum::ROLE_USER->value])
->setRegistrationDate(new \DateTimeImmutable('2024-03-01'))
->setLastActiveAt(new \DateTimeImmutable('2024-06-07'));

$mainOrgPasswordUser = new PasswordUser(
'e06f9972-6add-403d-82d9-bd7370b7668f',
self::PASSWORD,
$mainOrgUser,
);

$mainOtherAdmin = (new User('5bc831a3-7a09-44e9-aefa-5ce3588dac33'))
->setFullName('Mathieu FERNANDEZ')
->setEmail(self::MAIN_ORG_ADMIN_EMAIL)
->setPassword(self::PASSWORD)
->setRoles([UserRolesEnum::ROLE_SUPER_ADMIN->value])
->setRegistrationDate(new \DateTimeImmutable('2024-04-02'))
->setLastActiveAt(new \DateTimeImmutable('2024-06-08'));

$mainOtherPasswordAdmin = new PasswordUser(
'437dd344-0b78-4aa6-ba79-112cb6827516',
self::PASSWORD,
$mainOtherAdmin,
);

$otherOrgUser = (new User('d47badd9-989e-472b-a80e-9df642e93880'))
->setFullName('Florimond MANCA')
->setEmail(self::OTHER_ORG_USER_EMAIL)
->setPassword(self::PASSWORD)
->setRoles([UserRolesEnum::ROLE_USER->value])
->setRegistrationDate(new \DateTimeImmutable('2024-05-07'));

$otherOrgPasswordUser = new PasswordUser(
'7eb26f55-3029-4a61-b88b-30e2a97806ea',
self::PASSWORD,
$otherOrgUser,
);

$manager->persist($mainOrgUser);
$manager->persist($mainOtherAdmin);
$manager->persist($otherOrgUser);
$manager->persist($mainOrgPasswordUser);
$manager->persist($mainOtherPasswordAdmin);
$manager->persist($otherOrgPasswordUser);
$manager->flush();

$this->addReference('mainOrgUser', $mainOrgUser);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="App\Domain\User\PasswordUser" table="password_user">
<id name="uuid" type="guid" column="uuid"/>
<field name="password" type="string" column="password" nullable="false"/>
<one-to-one field="user" target-entity="App\Domain\User\User" inversed-by="passwordUser">
<join-column name="user_uuid" referenced-column-name="uuid" nullable="false" on-delete="CASCADE"/>
</one-to-one>
</entity>
</doctrine-mapping>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="App\Domain\User\ProConnectUser" table="proconnect_user">
<id name="uuid" type="guid" column="uuid"/>
<one-to-one field="user" target-entity="App\Domain\User\User" inversed-by="proConnectUser">
<join-column name="user_uuid" referenced-column-name="uuid" nullable="false" on-delete="CASCADE"/>
</one-to-one>
</entity>
</doctrine-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
<id name="uuid" type="guid" column="uuid"/>
<field name="fullName" type="string" column="full_name" nullable="false"/>
<field name="email" type="string" column="email" nullable="false"/>
<field name="password" type="string" column="password" nullable="false"/>
<field name="roles" type="array" column="roles" nullable="false"/>
<field name="registrationDate" type="datetimetz" nullable="false">
<options>
<option name="default">CURRENT_TIMESTAMP</option>
</options>
</field>
<field name="lastActiveAt" type="datetimetz" column="last_active_at" nullable="true" />
<one-to-one field="proConnectUser" target-entity="App\Domain\User\ProConnectUser" mapped-by="user" />
<one-to-one field="passwordUser" target-entity="App\Domain\User\PasswordUser" mapped-by="user" />
<unique-constraints>
<unique-constraint columns="email" name="user_email" />
</unique-constraints>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace App\Infrastructure\Persistence\Doctrine\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250113103218 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE password_user (uuid UUID NOT NULL, user_uuid UUID NOT NULL, password VARCHAR(255) NOT NULL, PRIMARY KEY(uuid))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1FC6D102ABFE1C6F ON password_user (user_uuid)');
$this->addSql('CREATE TABLE proconnect_user (uuid UUID NOT NULL, user_uuid UUID NOT NULL, PRIMARY KEY(uuid))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_9010F504ABFE1C6F ON proconnect_user (user_uuid)');
$this->addSql('ALTER TABLE password_user ADD CONSTRAINT FK_1FC6D102ABFE1C6F FOREIGN KEY (user_uuid) REFERENCES "user" (uuid) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE proconnect_user ADD CONSTRAINT FK_9010F504ABFE1C6F FOREIGN KEY (user_uuid) REFERENCES "user" (uuid) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('
INSERT INTO password_user (uuid, user_uuid, password)
SELECT uuid_generate_v4() AS uuid, u.uuid as user_uuid, u.password as password FROM public.user AS u
');
$this->addSql('ALTER TABLE "user" DROP password');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE password_user DROP CONSTRAINT FK_1FC6D102ABFE1C6F');
$this->addSql('ALTER TABLE proconnect_user DROP CONSTRAINT FK_9010F504ABFE1C6F');
$this->addSql('DROP TABLE password_user');
$this->addSql('DROP TABLE proconnect_user');
$this->addSql('ALTER TABLE "user" ADD password VARCHAR(255) NOT NULL');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Infrastructure\Persistence\Doctrine\Repository\User;

use App\Domain\User\PasswordUser;
use App\Domain\User\Repository\PasswordUserRepositoryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

final class PasswordUserRepository extends ServiceEntityRepository implements PasswordUserRepositoryInterface
{
public function __construct(
ManagerRegistry $registry,
) {
parent::__construct($registry, PasswordUser::class);
}

public function add(PasswordUser $passwordUser): PasswordUser
{
$this->getEntityManager()->persist($passwordUser);

return $passwordUser;
}
}
Loading

0 comments on commit aec6f43

Please sign in to comment.