Skip to content

Commit

Permalink
chore: PHPStan fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
roadiz-ci committed Aug 2, 2024
1 parent 1fadc51 commit 8939cf3
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 18 deletions.
10 changes: 10 additions & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ security:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
# Enable login-link feature
# https://symfony.com/doc/current/security/login_link.html
login_link:
check_route: login_link_check
signature_properties: [ 'id', 'email' ]
# lifetime in seconds
lifetime: 300
# only allow the link to be used 3 times
max_uses: 3
success_handler: RZ\Roadiz\CoreBundle\Security\Authentication\BackofficeAuthenticationSuccessHandler
login_throttling:
max_attempts: 3
logout:
Expand Down
6 changes: 0 additions & 6 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ services:
- '../src/Traits/'
- '../src/Kernel.php'
- '../src/Tests/'
- '../src/DataCollector/'
- '../src/Event/'
- '../src/Model/'
- '../src/ListManager/'
Expand Down Expand Up @@ -406,11 +405,6 @@ services:
RZ\Roadiz\CoreBundle\SearchEngine\ClientRegistry:
arguments: ['@service_container']

RZ\Roadiz\CoreBundle\SearchEngine\SolariumLogger:
tags:
- { name: data_collector, template: '@RoadizCore/DataCollector/solarium.html.twig', id: 'solarium' }
- { name: monolog.logger, channel: solr }

RZ\Roadiz\CoreBundle\SearchEngine\Indexer\IndexerFactory:
arguments: ['@service_container']

Expand Down
2 changes: 1 addition & 1 deletion src/Api/Filter/ArchiveFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Exception\FilterValidationException;
use ApiPlatform\Exception\FilterValidationException;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Filter/IntersectionFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Metadata\Exception\FilterValidationException;
use ApiPlatform\Exception\FilterValidationException;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Filter/LocaleFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace RZ\Roadiz\CoreBundle\Api\Filter;

use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Exception\FilterValidationException;
use ApiPlatform\Exception\FilterValidationException;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\SearchEngine;
namespace RZ\Roadiz\CoreBundle\DataCollector;

use Psr\Log\LoggerInterface;
use Solarium\Core\Client\Endpoint as SolariumEndpoint;
Expand All @@ -13,6 +13,7 @@
use Solarium\Core\Event\PreExecuteRequest as SolariumPreExecuteRequestEvent;
use Solarium\Core\Plugin\AbstractPlugin as SolariumPlugin;
use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
Expand All @@ -22,6 +23,14 @@
/**
* @see https://github.com/nelmio/NelmioSolariumBundle
*/
#[AutoconfigureTag('data_collector', [
'template' => '@RoadizCore/DataCollector/solarium.html.twig',
# must match the value returned by the getName() method
'id' => 'solarium',
])]
#[AutoconfigureTag('monolog.logger', [
'channel' => 'solr',
])]
final class SolariumLogger extends SolariumPlugin implements DataCollectorInterface, \Serializable, EventSubscriberInterface, TemplateAwareDataCollectorInterface
{
private array $data = [];
Expand Down
2 changes: 1 addition & 1 deletion src/DependencyInjection/RoadizCoreExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use RZ\Roadiz\CoreBundle\Cache\CloudflareProxyCache;
use RZ\Roadiz\CoreBundle\Cache\ReverseProxyCache;
use RZ\Roadiz\CoreBundle\Cache\ReverseProxyCacheLocator;
use RZ\Roadiz\CoreBundle\DataCollector\SolariumLogger;
use RZ\Roadiz\CoreBundle\Entity\CustomForm;
use RZ\Roadiz\CoreBundle\Entity\Document;
use RZ\Roadiz\CoreBundle\Entity\Node;
Expand All @@ -18,7 +19,6 @@
use RZ\Roadiz\CoreBundle\Entity\NodeType;
use RZ\Roadiz\CoreBundle\Entity\Translation;
use RZ\Roadiz\CoreBundle\Repository\NodesSourcesRepository;
use RZ\Roadiz\CoreBundle\SearchEngine\SolariumLogger;
use RZ\Roadiz\CoreBundle\Webhook\Message\GenericJsonPostMessage;
use RZ\Roadiz\CoreBundle\Webhook\Message\GitlabPipelineTriggerMessage;
use RZ\Roadiz\CoreBundle\Webhook\Message\NetlifyBuildHookMessage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\Security\Authentication;

use Doctrine\Persistence\ManagerRegistry;
use RZ\Roadiz\CoreBundle\Entity\User;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;

final class BackofficeAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
public function __construct(
private readonly UrlGeneratorInterface $urlGenerator,
private readonly ManagerRegistry $managerRegistry
) {
}
/**
* @inheritDoc
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token): ?Response
{
$user = $token->getUser();

if ($user instanceof User) {
$user->setLastLogin(new \DateTime('now'));
$manager = $this->managerRegistry->getManagerForClass(User::class);
$manager?->flush();
}

return new RedirectResponse($this->urlGenerator->generate('adminHomePage'));
}
}
4 changes: 1 addition & 3 deletions src/Security/Authentication/RoadizAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
if ($user instanceof User) {
$user->setLastLogin(new \DateTime('now'));
$manager = $this->managerRegistry->getManagerForClass(User::class);
if (null !== $manager) {
$manager->flush();
}
$manager?->flush();
}

if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
Expand Down
36 changes: 36 additions & 0 deletions src/Security/User/UserViewer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\LoginLink\LoginLinkDetails;
use Symfony\Contracts\Translation\TranslatorInterface;

final class UserViewer
Expand Down Expand Up @@ -93,6 +95,40 @@ public function sendPasswordResetLink(
}
}

public function sendLoginLink(
UserInterface $user,
LoginLinkDetails $loginLinkDetails,
string $htmlTemplate = '@RoadizCore/email/users/login_link_email.html.twig',
string $txtTemplate = '@RoadizCore/email/users/login_link_email.txt.twig'
): void {
if (!(($user instanceof User) && $user->isEnabled())) {
throw new \InvalidArgumentException('User must be enabled to send a login link.');
}

$emailManager = $this->emailManagerFactory->create();
$emailContact = $this->getContactEmail();
$siteName = $this->getSiteName();

$emailManager->setAssignation([
'loginLink' => $loginLinkDetails->getUrl(),
'expiresAt' => $loginLinkDetails->getExpiresAt(),
'user' => $user,
'site' => $siteName,
'mailContact' => $emailContact,
]);
$emailManager->setEmailTemplate($htmlTemplate);
$emailManager->setEmailPlainTextTemplate($txtTemplate);
$emailManager->setSubject($this->translator->trans(
'login_link.request'
));

$emailManager->setReceiver($user->getEmail());
$emailManager->setSender([$emailContact => $siteName]);

// Send the message
$emailManager->send();
}

/**
* @return string
*/
Expand Down
1 change: 1 addition & 0 deletions src/Serializer/TranslationAwareContextBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function createFromRequest(Request $request, bool $normalization, array $
$context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);

if (isset($context['translation']) && $context['translation'] instanceof TranslationInterface) {
// @phpstan-ignore-next-line
return $context;
}

Expand Down
39 changes: 39 additions & 0 deletions templates/email/users/login_link_email.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{% extends '@RoadizCore/email/base_email.html.twig' %}

{% block title %}<title>{% trans %}login_link.request{% endtrans %}</title>{% endblock %}

{% block content_table %}
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
{% block content_title %}
<h1 itemprop="name">{% trans %}login_link.request{% endtrans %}</h1>
{% endblock %}
</td>
</tr>
<tr>
<td class="content-block">
<table class="invoice" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
<tr>
<td class="content-block">
{% block content_subtitle %}
<h2>{{ 'you.asked.for.a.login_link.on.site'|trans({'%site%':site})|escape }}</h2>
{% endblock %}
</td>
</tr>
<tr>
<td>
<p>{% trans %}click_on_following_link_to_login{% endtrans %}</p>
<p>{{ 'login_link_will_expire_at.expiresAt'|trans({
'%expiresAt%': expiresAt|format_datetime('short', 'short'),
}) }}</p>
<p class="aligncenter" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
<a class="btn-primary" href="{{ loginLink }}" itemprop="url">{% trans %}login{% endtrans %}</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
{% endblock %}
16 changes: 16 additions & 0 deletions templates/email/users/login_link_email.txt.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends '@RoadizCore/email/base_email.txt.twig' %}

{% block title %}{% trans %}login_link.request{% endtrans %}{% endblock %}
{% block content_subtitle %}{{ 'you.asked.for.a.login_link.on.site'|trans({'%site%':site})|escape }}{% endblock %}

{% block content_table %}
{% trans %}click_on_following_link_to_login{% endtrans %}
{{ 'login_link_will_expire_at.expiresAt'|trans({
'%expiresAt%': expiresAt|format_datetime('short', 'short'),
}) }}

---
{{ loginLink }}
---

{% endblock %}
42 changes: 40 additions & 2 deletions translations/core/messages.en.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,52 @@
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.defaultRealm.placeholder">
<source>attributes.defaultRealm.placeholder</source>

<target state="translated">-- No default realm --</target>
<note>Default text when no realm is attached to an attribute</note></trans-unit>
<trans-unit xml:space="preserve" id="attributeValue.realm.placeholder">
<source>attributeValue.realm.placeholder</source>

<target state="translated">-- No realm --</target>
<note>Default text when no realm is attached to an attribute-value</note></trans-unit>


<trans-unit xml:space="preserve" id="login_link">
<source>login_link</source>
<target state="final">Login link</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_sent">
<source>login_link_sent</source>
<target state="final">A login link was sent</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_sent_if_email_exists.check_inbox">
<source>login_link_sent_if_email_exists.check_inbox</source>
<target state="final">A login link was sent to your email address if your account is valid. Check your inbox.</target>
</trans-unit>
<trans-unit xml:space="preserve" id="request_login_link">
<source>request_login_link</source>
<target state="final">Request a login link</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link.request">
<source>login_link.request</source>
<target state="final">Your login link</target>
</trans-unit>
<trans-unit xml:space="preserve" id="you.asked.for.a.login_link.on.site">
<source>you.asked.for.a.login_link.on.site</source>
<target state="final">You requested a login link for website: %site%</target>
</trans-unit>
<trans-unit xml:space="preserve" id="click_on_following_link_to_login">
<source>click_on_following_link_to_login</source>
<target state="final">Click on the following link to login automatically.</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_will_expire_at.expiresAt">
<source>login_link_will_expire_at.expiresAt</source>
<target state="final">This link will expire on %expiresAt%</target>
</trans-unit>
<trans-unit xml:space="preserve" id="classic.login_password">
<source>classic.login_password</source>
<target state="final">Password login</target>
</trans-unit>
</body>
</file>
</xliff>
41 changes: 39 additions & 2 deletions translations/core/messages.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,51 @@
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.defaultRealm.placeholder" approved="yes">
<source>attributes.defaultRealm.placeholder</source>

<target state="final">-- Aucun domaine sécurisé par défaut --</target>
<note>Default text when no realm is attached to an attribute</note></trans-unit>
<trans-unit xml:space="preserve" id="attributeValue.realm.placeholder" approved="yes">
<source>attributeValue.realm.placeholder</source>

<target state="final">-- Aucun domaine sécurisé --</target>
<note>Default text when no realm is attached to an attribute-value</note></trans-unit>

<trans-unit xml:space="preserve" id="login_link">
<source>login_link</source>
<target state="final">Lien de connexion</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_sent">
<source>login_link_sent</source>
<target state="final">Un lien de connexion vous a été envoyé</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_sent_if_email_exists.check_inbox">
<source>login_link_sent_if_email_exists.check_inbox</source>
<target state="final">Un lien de connexion vous a été envoyé par email si votre compte est valide, veuillez vérifier votre boîte de réception.</target>
</trans-unit>
<trans-unit xml:space="preserve" id="request_login_link">
<source>request_login_link</source>
<target state="final">Demander un lien de connexion</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link.request">
<source>login_link.request</source>
<target state="final">Votre lien de connexion</target>
</trans-unit>
<trans-unit xml:space="preserve" id="you.asked.for.a.login_link.on.site">
<source>you.asked.for.a.login_link.on.site</source>
<target state="final">Vous avez fait une demande de connexion sur le site : %site%</target>
</trans-unit>
<trans-unit xml:space="preserve" id="click_on_following_link_to_login">
<source>click_on_following_link_to_login</source>
<target state="final">Cliquez sur le lien suivant pour vous connecter automatiquement.</target>
</trans-unit>
<trans-unit xml:space="preserve" id="login_link_will_expire_at.expiresAt">
<source>login_link_will_expire_at.expiresAt</source>
<target state="final">Ce lien expirera le %expiresAt%</target>
</trans-unit>
<trans-unit xml:space="preserve" id="classic.login_password">
<source>classic.login_password</source>
<target state="final">Se connecter avec mot de passe</target>
</trans-unit>
</body>
</file>
</xliff>
Loading

0 comments on commit 8939cf3

Please sign in to comment.