Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Core/src/App/src/Entity/AbstractEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ public function getUuid(): UuidInterface
return $this->uuid;
}

/**
* Override this method in soft-deletable entities
*/
public function isDeleted(): bool
{
return false;
}

public function exchangeArray(array $array): void
{
foreach ($array as $property => $values) {
Expand Down
14 changes: 14 additions & 0 deletions src/Core/src/App/src/Entity/EntityInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@

namespace Core\App\Entity;

use DateTimeImmutable;
use Ramsey\Uuid\UuidInterface;

interface EntityInterface
{
public function getUuid(): UuidInterface;

public function getCreated(): ?DateTimeImmutable;

public function getCreatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): string;

public function getUpdated(): ?DateTimeImmutable;

public function getUpdatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): ?string;

public function isDeleted(): bool;
}
5 changes: 1 addition & 4 deletions src/Core/src/App/src/Entity/RoleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
namespace Core\App\Entity;

use BackedEnum;
use Ramsey\Uuid\UuidInterface;

interface RoleInterface
interface RoleInterface extends EntityInterface
{
public function getUuid(): UuidInterface;

public function getName(): ?BackedEnum;

public function setName(BackedEnum $name): RoleInterface;
Expand Down
39 changes: 39 additions & 0 deletions src/Core/src/App/src/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Core\App;

use function count;
use function implode;
use function sprintf;

Expand Down Expand Up @@ -34,18 +35,23 @@ class Message
. 'you will receive an email with further instructions on resetting your account\'s password.';
public const MAIL_SENT_USER_ACTIVATION = 'User activation mail has been successfully sent to "%s"';
public const MISSING_CONFIG = 'Missing configuration value: "%s".';
public const NOT_ACCEPTABLE = 'Not acceptable.';
public const RESET_PASSWORD_EXPIRED = 'Reset password hash is invalid (expired).';
public const RESET_PASSWORD_NOT_FOUND = 'Reset password request not found.';
public const RESET_PASSWORD_OK = 'Password successfully modified.';
public const RESET_PASSWORD_USED = 'Reset password hash is invalid (used).';
public const RESET_PASSWORD_VALID = 'Reset password hash is valid.';
public const RESOURCE_ALREADY_REGISTERED = 'Resource "%s" is already registered.';
public const RESOURCE_NOT_ALLOWED = 'You are not allowed to access this resource.';
public const RESOURCE_NOT_FOUND = '%s not found.';
public const RESTRICTION_DEPRECATION = 'Cannot use both "%s" and "%s" attributes on the same object.';
public const RESTRICTION_IMAGE = 'File must be an image> Accepted mim type(s): %s';
public const RESTRICTION_ROLES = 'At least one role is required.';
public const ROLE_NOT_FOUND = 'Role not found.';
public const SERVICE_NOT_FOUND = 'Service %s not found in the container.';
public const SETTING_NOT_FOUND = 'Setting "%s" not found.';
public const TEMPLATE_NOT_FOUND = 'Template "%s" not found.';
public const UNSUPPORTED_MEDIA_TYPE = 'Unsupported Media Type.';
public const USER_ACTIVATED = 'User account has been activated.';
public const USER_ALREADY_ACTIVATED = 'User account is already active.';
public const USER_ALREADY_DEACTIVATED = 'User account is already inactive.';
Expand Down Expand Up @@ -93,6 +99,25 @@ public static function mailSentUserActivation(string $email): string
return sprintf(self::MAIL_SENT_USER_ACTIVATION, $email);
}

public static function notAcceptable(array $types = []): string
{
if (count($types) === 0) {
return self::NOT_ACCEPTABLE;
}

return sprintf('%s Supported types: %s', self::NOT_ACCEPTABLE, implode(', ', $types));
}

public static function resourceAlreadyRegistered(string $resource): string
{
return sprintf(self::RESOURCE_ALREADY_REGISTERED, $resource);
}

public static function resourceNotFound(string $resource = 'Resource'): string
{
return sprintf(self::RESOURCE_NOT_FOUND, $resource);
}

public static function restrictionDeprecation(string $first, string $second): string
{
return sprintf(self::RESTRICTION_DEPRECATION, $first, $second);
Expand All @@ -113,6 +138,20 @@ public static function settingNotFound(string $identifier): string
return sprintf(self::SETTING_NOT_FOUND, $identifier);
}

public static function templateNotFound(string $template): string
{
return sprintf(self::TEMPLATE_NOT_FOUND, $template);
}

public static function unsupportedMediaType(array $types = []): string
{
if (count($types) === 0) {
return self::UNSUPPORTED_MEDIA_TYPE;
}

return sprintf('%s Supported types: %s', self::UNSUPPORTED_MEDIA_TYPE, implode(', ', $types));
}

public static function validatorLengthMax(int $max): string
{
return sprintf(self::VALIDATOR_LENGTH_MAX, $max);
Expand Down
54 changes: 13 additions & 41 deletions src/Core/src/App/src/Service/MailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@
use Dot\DependencyInjection\Attribute\Inject;
use Dot\Log\LoggerInterface;
use Dot\Mail\Exception\MailException;
use Mezzio\Template\TemplateRendererInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;

use function sprintf;

class MailService
{
#[Inject(
TemplateRendererInterface::class,
'dot-mail.service.default',
'dot-log.default_logger',
'config',
)]
public function __construct(
private readonly TemplateRendererInterface $templateRenderer,
protected \Dot\Mail\Service\MailService $mailService,
protected LoggerInterface $logger,
private readonly array $config,
Expand All @@ -33,20 +30,15 @@ public function __construct(
/**
* @throws MailException
*/
public function sendActivationMail(User $user): bool
public function sendActivationMail(User $user, string $body): bool
{
if ($user->isActive()) {
return false;
}

$this->mailService->getMessage()->addTo($user->getDetail()->getEmail(), $user->getName());
$this->mailService->setSubject('Welcome to ' . $this->config['application']['name']);
$this->mailService->setBody(
$this->templateRenderer->render('user::activate', [
'config' => $this->config,
'user' => $user,
])
);
$this->mailService->setBody($body);

try {
return $this->mailService->send()->isValid();
Expand All @@ -59,18 +51,13 @@ public function sendActivationMail(User $user): bool
/**
* @throws MailException
*/
public function sendResetPasswordRequestedMail(User $user): bool
public function sendResetPasswordRequestedMail(User $user, string $body): bool
{
$this->mailService->getMessage()->addTo($user->getDetail()->getEmail(), $user->getName());
$this->mailService->setSubject(
'Reset password instructions for your ' . $this->config['application']['name'] . ' account'
);
$this->mailService->setBody(
$this->templateRenderer->render('user::reset-password-requested', [
'config' => $this->config,
'user' => $user,
])
);
$this->mailService->setBody($body);

try {
return $this->mailService->send()->isValid();
Expand All @@ -83,18 +70,13 @@ public function sendResetPasswordRequestedMail(User $user): bool
/**
* @throws MailException
*/
public function sendResetPasswordCompletedMail(User $user): bool
public function sendResetPasswordCompletedMail(User $user, string $body): bool
{
$this->mailService->getMessage()->addTo($user->getDetail()->getEmail(), $user->getName());
$this->mailService->setSubject(
'You have successfully reset the password for your ' . $this->config['application']['name'] . ' account'
);
$this->mailService->setBody(
$this->templateRenderer->render('user::reset-password-completed', [
'config' => $this->config,
'user' => $user,
])
);
$this->mailService->setBody($body);

try {
return $this->mailService->send()->isValid();
Expand All @@ -107,16 +89,13 @@ public function sendResetPasswordCompletedMail(User $user): bool
/**
* @throws MailException
*/
public function sendWelcomeMail(User $user): bool
public function sendRecoverIdentityMail(User $user, string $body): bool
{
$this->mailService->getMessage()->addTo($user->getDetail()->getEmail(), $user->getName());
$this->mailService->setSubject('Welcome to ' . $this->config['application']['name']);
$this->mailService->setBody(
$this->templateRenderer->render('user::welcome', [
'config' => $this->config,
'user' => $user,
])
$this->mailService->setSubject(
'Recover identity for your ' . $this->config['application']['name'] . ' account'
);
$this->mailService->setBody($body);

try {
return $this->mailService->send()->isValid();
Expand All @@ -129,18 +108,11 @@ public function sendWelcomeMail(User $user): bool
/**
* @throws MailException
*/
public function sendRecoverIdentityMail(User $user): bool
public function sendWelcomeMail(User $user, string $body): bool
{
$this->mailService->getMessage()->addTo($user->getDetail()->getEmail(), $user->getName());
$this->mailService->setSubject(
'Recover identity for your ' . $this->config['application']['name'] . ' account'
);
$this->mailService->setBody(
$this->templateRenderer->render('user::recover-identity-requested', [
'config' => $this->config,
'user' => $user,
])
);
$this->mailService->setSubject('Welcome to ' . $this->config['application']['name']);
$this->mailService->setBody($body);

try {
return $this->mailService->send()->isValid();
Expand Down
4 changes: 2 additions & 2 deletions src/Core/src/Setting/src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __invoke(): array
];
}

public function getDependencies(): array
private function getDependencies(): array
{
return [
'factories' => [
Expand All @@ -28,7 +28,7 @@ public function getDependencies(): array
];
}

public function getDoctrineConfig(): array
private function getDoctrineConfig(): array
{
return [
'driver' => [
Expand Down
14 changes: 2 additions & 12 deletions src/Core/src/User/src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use function array_map;
use function bin2hex;
use function md5;
use function trim;
use function uniqid;

#[ORM\Entity(repositoryClass: UserRepository::class)]
Expand Down Expand Up @@ -116,17 +117,6 @@ public function addResetPassword(UserResetPassword $resetPassword): void
$this->resetPasswords->add($resetPassword);
}

public function createResetPassword(): self
{
$this->resetPasswords->add(
(new UserResetPassword())
->setHash(self::generateHash())
->setUser($this)
);

return $this;
}

public function getResetPasswords(): Collection
{
return $this->resetPasswords;
Expand Down Expand Up @@ -261,7 +251,7 @@ public static function generateHash(): string

public function getName(): string
{
return $this->getDetail()->getFirstName() . ' ' . $this->getDetail()->getLastName();
return trim($this->getDetail()->getFirstName() . ' ' . $this->getDetail()->getLastName());
}

public function isActive(): bool
Expand Down
8 changes: 7 additions & 1 deletion src/User/src/Handler/PostUserCreateHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class PostUserCreateHandler implements RequestHandlerInterface
CreateUserForm::class,
MailService::class,
'dot-log.default_logger',
'config',
)]
public function __construct(
protected UserServiceInterface $userService,
Expand All @@ -44,6 +45,7 @@ public function __construct(
protected CreateUserForm $createUserForm,
protected MailService $mailService,
protected Logger $logger,
protected array $config,
) {
}

Expand All @@ -58,7 +60,11 @@ public function handle(ServerRequestInterface $request): ResponseInterface
$user = $this->userService->saveUser((array) $this->createUserForm->getData());
$this->messenger->addSuccess(Message::USER_CREATED);
if ($user->getDetail()->hasEmail()) {
$this->mailService->sendWelcomeMail($user);
$body = $this->template->render('user::welcome', [
'config' => $this->config,
'user' => $user,
]);
$this->mailService->sendWelcomeMail($user, $body);
}

return new EmptyResponse(StatusCodeInterface::STATUS_CREATED);
Expand Down
21 changes: 21 additions & 0 deletions test/Unit/App/Entity/AbstractEntityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use AdminTest\Unit\UnitTest;
use Core\App\Entity\AbstractEntity;
use Core\App\Entity\EntityInterface;
use DateTimeImmutable;
use Ramsey\Uuid\UuidInterface;

class AbstractEntityTest extends UnitTest
Expand All @@ -18,6 +19,26 @@ public function getArrayCopy(): array
{
return [];
}

public function getCreated(): ?DateTimeImmutable
{
return null;
}

public function getCreatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): string
{
return '';
}

public function getUpdated(): ?DateTimeImmutable
{
return null;
}

public function getUpdatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): ?string
{
return null;
}
};

$this->assertContainsOnlyInstancesOf(EntityInterface::class, [$entity]);
Expand Down
Loading