diff --git a/com.woltlab.wcf/eventListener.xml b/com.woltlab.wcf/eventListener.xml
index 3fb2f656d55..20179f8bdef 100644
--- a/com.woltlab.wcf/eventListener.xml
+++ b/com.woltlab.wcf/eventListener.xml
@@ -39,5 +39,10 @@
wcf\system\event\listener\UserLinkHtmlInputNodeProcessorListener
all
+
+ wcf\system\user\authentication\event\UserLoggedIn
+ wcf\system\event\listener\UserLoginCancelLostPasswordListener
+ all
+
diff --git a/wcfsetup/install/files/lib/acp/form/LoginForm.class.php b/wcfsetup/install/files/lib/acp/form/LoginForm.class.php
index 7d36887dec0..845e9f724cb 100755
--- a/wcfsetup/install/files/lib/acp/form/LoginForm.class.php
+++ b/wcfsetup/install/files/lib/acp/form/LoginForm.class.php
@@ -8,12 +8,14 @@
use wcf\data\user\UserProfile;
use wcf\form\AbstractCaptchaForm;
use wcf\system\application\ApplicationHandler;
+use wcf\system\event\EventHandler;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\UserInputException;
use wcf\system\request\LinkHandler;
use wcf\system\request\RequestHandler;
use wcf\system\request\RouteHandler;
use wcf\system\user\authentication\EmailUserAuthentication;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\authentication\UserAuthenticationFactory;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
@@ -226,6 +228,10 @@ public function save()
$needsMultifactor = WCF::getSession()->changeUserAfterMultifactorAuthentication($this->user);
if (!$needsMultifactor) {
WCF::getSession()->registerReauthentication();
+
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($this->user)
+ );
}
$this->saved();
diff --git a/wcfsetup/install/files/lib/action/FacebookAuthAction.class.php b/wcfsetup/install/files/lib/action/FacebookAuthAction.class.php
index c5276b38469..35bd06f3ed1 100644
--- a/wcfsetup/install/files/lib/action/FacebookAuthAction.class.php
+++ b/wcfsetup/install/files/lib/action/FacebookAuthAction.class.php
@@ -5,8 +5,10 @@
use GuzzleHttp\Psr7\Request;
use wcf\data\user\User;
use wcf\form\RegisterForm;
+use wcf\system\event\EventHandler;
use wcf\system\exception\NamedUserException;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\authentication\oauth\User as OauthUser;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
@@ -135,6 +137,10 @@ protected function processUser(OauthUser $oauthUser)
WCF::getSession()->changeUser($user);
WCF::getSession()->update();
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($user)
+ );
+
HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
exit;
diff --git a/wcfsetup/install/files/lib/action/GithubAuthAction.class.php b/wcfsetup/install/files/lib/action/GithubAuthAction.class.php
index a8a034e3b1b..1efc49a2b19 100644
--- a/wcfsetup/install/files/lib/action/GithubAuthAction.class.php
+++ b/wcfsetup/install/files/lib/action/GithubAuthAction.class.php
@@ -6,8 +6,10 @@
use Psr\Http\Client\ClientExceptionInterface;
use wcf\data\user\User;
use wcf\form\RegisterForm;
+use wcf\system\event\EventHandler;
use wcf\system\exception\NamedUserException;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\authentication\oauth\User as OauthUser;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
@@ -125,6 +127,10 @@ protected function processUser(OauthUser $oauthUser)
WCF::getSession()->changeUser($user);
WCF::getSession()->update();
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($user)
+ );
+
HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
exit;
diff --git a/wcfsetup/install/files/lib/action/GoogleAuthAction.class.php b/wcfsetup/install/files/lib/action/GoogleAuthAction.class.php
index 078e9b64259..169d77bac91 100644
--- a/wcfsetup/install/files/lib/action/GoogleAuthAction.class.php
+++ b/wcfsetup/install/files/lib/action/GoogleAuthAction.class.php
@@ -5,8 +5,10 @@
use GuzzleHttp\Psr7\Request;
use wcf\data\user\User;
use wcf\form\RegisterForm;
+use wcf\system\event\EventHandler;
use wcf\system\exception\NamedUserException;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\authentication\oauth\User as OauthUser;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
@@ -147,6 +149,10 @@ protected function processUser(OauthUser $oauthUser)
WCF::getSession()->changeUser($user);
WCF::getSession()->update();
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($user)
+ );
+
HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
exit;
diff --git a/wcfsetup/install/files/lib/action/TwitterAuthAction.class.php b/wcfsetup/install/files/lib/action/TwitterAuthAction.class.php
index 1975bd10e90..5b287412c3d 100644
--- a/wcfsetup/install/files/lib/action/TwitterAuthAction.class.php
+++ b/wcfsetup/install/files/lib/action/TwitterAuthAction.class.php
@@ -8,10 +8,12 @@
use ParagonIE\ConstantTime\Hex;
use Psr\Http\Client\ClientExceptionInterface;
use wcf\data\user\User;
+use wcf\system\event\EventHandler;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\io\HttpFactory;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\authentication\oauth\exception\StateValidationException;
use wcf\system\user\authentication\oauth\User as OauthUser;
use wcf\system\WCF;
@@ -121,6 +123,10 @@ protected function processUser(OauthUser $oauthUser)
WCF::getSession()->changeUser($user);
WCF::getSession()->update();
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($user)
+ );
+
HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
exit;
diff --git a/wcfsetup/install/files/lib/data/user/UserAction.class.php b/wcfsetup/install/files/lib/data/user/UserAction.class.php
index 2bb22707cdd..a43fced14d9 100644
--- a/wcfsetup/install/files/lib/data/user/UserAction.class.php
+++ b/wcfsetup/install/files/lib/data/user/UserAction.class.php
@@ -1235,4 +1235,21 @@ public function devtoolsSetLanguage()
'languageID' => $this->parameters['languageID'],
]);
}
+
+ /**
+ * @since 5.5
+ */
+ public function cancelLostPasswordRequest(): void
+ {
+ if (empty($this->objects)) {
+ $this->readObjects();
+ }
+
+ foreach ($this->getObjects() as $userEditor) {
+ $userEditor->update([
+ 'lastLostPasswordRequestTime' => 0,
+ 'lostPasswordKey' => '',
+ ]);
+ }
+ }
}
diff --git a/wcfsetup/install/files/lib/form/LoginForm.class.php b/wcfsetup/install/files/lib/form/LoginForm.class.php
index 95fadd5b494..7dbd1c6a43d 100644
--- a/wcfsetup/install/files/lib/form/LoginForm.class.php
+++ b/wcfsetup/install/files/lib/form/LoginForm.class.php
@@ -2,7 +2,9 @@
namespace wcf\form;
+use wcf\system\event\EventHandler;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\WCF;
/**
@@ -31,6 +33,12 @@ public function save()
// change user
$needsMultifactor = WCF::getSession()->changeUserAfterMultifactorAuthentication($this->user);
+ if (!$needsMultifactor) {
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($this->user)
+ );
+ }
+
$this->saved();
// redirect to url
diff --git a/wcfsetup/install/files/lib/form/MultifactorAuthenticationForm.class.php b/wcfsetup/install/files/lib/form/MultifactorAuthenticationForm.class.php
index 57c87c273f3..4c0a5d194b1 100644
--- a/wcfsetup/install/files/lib/form/MultifactorAuthenticationForm.class.php
+++ b/wcfsetup/install/files/lib/form/MultifactorAuthenticationForm.class.php
@@ -6,10 +6,12 @@
use wcf\data\user\User;
use wcf\system\application\ApplicationHandler;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\event\EventHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\NamedUserException;
use wcf\system\form\builder\TemplateFormNode;
use wcf\system\request\LinkHandler;
+use wcf\system\user\authentication\event\UserLoggedIn;
use wcf\system\user\multifactor\IMultifactorMethod;
use wcf\system\user\multifactor\Setup;
use wcf\system\WCF;
@@ -144,6 +146,9 @@ public function save()
WCF::getDB()->commitTransaction();
WCF::getSession()->applyPendingUserChange($this->user);
+ EventHandler::getInstance()->fire(
+ new UserLoggedIn($this->user)
+ );
$this->saved();
}
diff --git a/wcfsetup/install/files/lib/system/event/listener/UserLoginCancelLostPasswordListener.class.php b/wcfsetup/install/files/lib/system/event/listener/UserLoginCancelLostPasswordListener.class.php
new file mode 100644
index 00000000000..606190fa45b
--- /dev/null
+++ b/wcfsetup/install/files/lib/system/event/listener/UserLoginCancelLostPasswordListener.class.php
@@ -0,0 +1,28 @@
+
+ * @package WoltLabSuite\Core\System\Event\Listener
+ * @since 5.5
+ */
+final class UserLoginCancelLostPasswordListener
+{
+ public function __invoke(UserLoggedIn $event)
+ {
+ $user = $event->getUser();
+ if (!$user->lostPasswordKey) {
+ return;
+ }
+
+ (new UserAction([$user], 'cancelLostPasswordRequest'))->executeAction();
+ }
+}
diff --git a/wcfsetup/install/files/lib/system/user/authentication/event/UserLoggedIn.class.php b/wcfsetup/install/files/lib/system/user/authentication/event/UserLoggedIn.class.php
new file mode 100644
index 00000000000..637d8646ce5
--- /dev/null
+++ b/wcfsetup/install/files/lib/system/user/authentication/event/UserLoggedIn.class.php
@@ -0,0 +1,39 @@
+
+ * @package WoltLabSuite\Core\System\User\Authentication\Event
+ * @since 5.5
+ */
+final class UserLoggedIn implements IEvent
+{
+ /**
+ * @var int
+ */
+ private $userID;
+
+ public function __construct(User $user)
+ {
+ $this->userID = (int)$user->userID;
+ }
+
+ public function getUser(): User
+ {
+ return UserRuntimeCache::getInstance()->getObject($this->userID);
+ }
+}