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
3 changes: 2 additions & 1 deletion app/config/services_test.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
services:
AppBundle\Listener\DetectClockMockingListener:
autowire: true
tags: [ kernel.event_listener ]
tags:
- { name: kernel.event_listener, priority: 1000 }
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ce changement c'est pour que ce listener soit exécuté en tout premier, et surtout avant celui ajouté dans cette PR.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class AddLastLoginToPersonnesPhysiques extends AbstractMigration
{
public function change(): void
{
$this->table('afup_personnes_physiques')
->addColumn('last_login', 'datetime', ['null' => true])
->save();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ private function getQueryBuilderWithCompleteUser()
'app.`adresse`', 'app.`code_postal`', 'app.`ville`', 'app.`id_pays`', 'app.`telephone_fixe`',
'app.`telephone_portable`', 'app.`etat`', 'app.`date_relance`', 'app.`compte_svn`',
'app.`slack_invite_status`', 'app.`slack_alternate_email`', 'app.`needs_up_to_date_membership`',
'app.`nearest_office`',
'app.`nearest_office`', 'app.`last_login`',
'MD5(CONCAT(app.`id`, \'_\', app.`email`, \'_\', app.`login`)) as hash',
"MAX(ac.date_fin) AS lastsubcription",
]);
Expand Down Expand Up @@ -601,6 +601,15 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
'type' => 'bool',
'serializer' => Boolean::class,
])
->addField([
'columnName' => 'last_login',
'fieldName' => 'lastLogin',
'type' => 'datetime_immutable',
'serializer_options' => [
'unserialize' => ['unSerializeUseFormat' => true, 'format' => 'Y-m-d H:i:s'],
'serialize' => ['serializeUseFormat' => true, 'format' => 'Y-m-d H:i:s'],
],
])
;

return $metadata;
Expand Down
14 changes: 14 additions & 0 deletions sources/AppBundle/Association/Model/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class User implements NotifyPropertyInterface, NotifiableInterface, UserInterfac
*/
private $needsUpToDateMembership = false;

private ?\DateTimeImmutable $lastLogin = null;

/**
* @return int
*/
Expand Down Expand Up @@ -503,6 +505,18 @@ public function setReminderDate(\DateTime $reminderDate = null): self
return $this;
}

public function getLastLogin(): ?\DateTimeImmutable
{
return $this->lastLogin;
}

public function setLastLogin(?\DateTimeImmutable $lastLogin): self
{
$this->propertyChanged('lastLogin', $this->lastLogin, $lastLogin);
$this->lastLogin = $lastLogin;
return $this;
}

/**
* @return string
*/
Expand Down
32 changes: 32 additions & 0 deletions sources/AppBundle/Security/LoginSuccessListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace AppBundle\Security;

use AppBundle\Association\Model\Repository\UserRepository;
use AppBundle\Association\Model\User;
use Psr\Clock\ClockInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;

#[AsEventListener]
final readonly class LoginSuccessListener
{
public function __construct(
private UserRepository $userRepository,
private ClockInterface $clock,
) {}

public function __invoke(LoginSuccessEvent $event): void
{
$user = $event->getAuthenticatedToken()->getUser();

if (!$user instanceof User) {
return;
}

$user->setLastLogin($this->clock->now());
$this->userRepository->save($user);
}
}
7 changes: 7 additions & 0 deletions templates/admin/members/user_edit.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
</a>
{% endif %}
{% endif %}
<span class="item">
{% if user.lastLogin %}
Dernière connexion : {{ user.lastLogin|date('d/m/Y H:i:s') }}
{% else %}
<em>Aucune connexion</em>
{% endif %}
</span>
</div>

<div class="ui segment">
Expand Down
19 changes: 19 additions & 0 deletions tests/behat/features/PublicSite/Login.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Feature: Page de connexion

@reloadDbWithTestData
Scenario: Aucune connexion
Given I am logged in as admin and on the Administration
When I follow "Personnes physiques"
And I follow the button of tooltip "Modifier la fiche de Personne Paul"
Then I should see "Aucune connexion"

@reloadDbWithTestData
Scenario: Date de dernière connexion enregistrée
Given the current date is "2026-03-10 13:56:28"
And I am logged-in with the user paul and the password paul
And I follow "Se déconnecter"
When the current date is "2026-03-20 09:12:34"
And I am logged in as admin and on the Administration
And I follow "Personnes physiques"
And I follow the button of tooltip "Modifier la fiche de Personne Paul"
Then I should see "Dernière connexion : 10/03/2026 13:56:28"
Loading