From fe1ba6ca47582b9f110cd813a0eba797b4ce4063 Mon Sep 17 00:00:00 2001 From: Cyperghost Date: Thu, 6 Feb 2025 09:52:46 +0100 Subject: [PATCH] Migrate `UserAuthenticationFailureListPage` to grid view --- .../userAuthenticationFailureList.tpl | 142 +----------------- ...serAuthenticationFailureListPage.class.php | 131 ++-------------- .../UserAuthenticationFailure.class.php | 1 + ...cationFailureGridViewInitialized.class.php | 21 +++ ...serAuthenticationFailureGridView.class.php | 132 ++++++++++++++++ 5 files changed, 169 insertions(+), 258 deletions(-) create mode 100644 wcfsetup/install/files/lib/event/gridView/admin/UserAuthenticationFailureGridViewInitialized.class.php create mode 100644 wcfsetup/install/files/lib/system/gridView/admin/UserAuthenticationFailureGridView.class.php diff --git a/wcfsetup/install/files/acp/templates/userAuthenticationFailureList.tpl b/wcfsetup/install/files/acp/templates/userAuthenticationFailureList.tpl index 278adcc978e..3b81d62b441 100644 --- a/wcfsetup/install/files/acp/templates/userAuthenticationFailureList.tpl +++ b/wcfsetup/install/files/acp/templates/userAuthenticationFailureList.tpl @@ -2,7 +2,7 @@
-

{lang}wcf.acp.user.authentication.failure.list{/lang}{if $items} {#$items}{/if}

+

{lang}wcf.acp.user.authentication.failure.list{/lang} {#$gridView->countRows()}

{hascontent} @@ -14,142 +14,8 @@ {/hascontent}
-
-
-

{lang}wcf.global.filter{/lang}

- -
-
-
-
- -
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
-
- -
-
- - {event name='filterFields'} -
- -
- - {csrfToken} -
-
-
- -{hascontent} -
- {content} - {pages print=true assign=pagesLinks controller='UserAuthenticationFailureList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$filterLinkParameters"} - {/content} -
-{/hascontent} - -{if $objects|count} -
- - - - - - - - - - - - {event name='columnHeads'} - - - - - {foreach from=$objects item='authenticationFailure'} - - - - - - - - - - {event name='columns'} - - {/foreach} - -
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.user.authentication.failure.environment{/lang}{lang}wcf.user.username{/lang}{lang}wcf.acp.user.authentication.failure.time{/lang}{lang}wcf.acp.user.authentication.failure.validationError{/lang}{lang}wcf.user.ipAddress{/lang}{lang}wcf.user.userAgent{/lang}
{@$authenticationFailure->failureID}{lang}wcf.acp.user.authentication.failure.environment.{@$authenticationFailure->environment}{/lang} - {if $authenticationFailure->userID} - {$authenticationFailure->username} - {else} - {$authenticationFailure->username} - {/if} - {@$authenticationFailure->time|time} - {if $authenticationFailure->validationError} - {lang}wcf.acp.user.authentication.failure.validationError.{$authenticationFailure->validationError}{/lang} - {/if} - {$authenticationFailure->getIpAddress()}{$authenticationFailure->userAgent|truncate:75|tableWordwrap}
-
- - -{else} - {lang}wcf.global.noItems{/lang} -{/if} +
+ {unsafe:$gridView->render()} +
{include file='footer'} diff --git a/wcfsetup/install/files/lib/acp/page/UserAuthenticationFailureListPage.class.php b/wcfsetup/install/files/lib/acp/page/UserAuthenticationFailureListPage.class.php index 997e269e250..574311f73c3 100644 --- a/wcfsetup/install/files/lib/acp/page/UserAuthenticationFailureListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/UserAuthenticationFailureListPage.class.php @@ -2,20 +2,20 @@ namespace wcf\acp\page; -use wcf\data\user\authentication\failure\UserAuthenticationFailureList; -use wcf\page\SortablePage; -use wcf\system\WCF; +use wcf\page\AbstractGridViewPage; +use wcf\system\gridView\AbstractGridView; +use wcf\system\gridView\admin\UserAuthenticationFailureGridView; /** * Shows a list of user authentication failures. * - * @author Marcel Werk - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License + * @author Olaf Braun, Marcel Werk + * @copyright 2001-2025 WoltLab GmbH + * @license GNU Lesser General Public License * - * @property UserAuthenticationFailureList $objectList + * @property UserAuthenticationFailureGridView $gridView */ -class UserAuthenticationFailureListPage extends SortablePage +class UserAuthenticationFailureListPage extends AbstractGridViewPage { /** * @inheritDoc @@ -32,118 +32,9 @@ class UserAuthenticationFailureListPage extends SortablePage */ public $neededModules = ['ENABLE_USER_AUTHENTICATION_FAILURE']; - /** - * @inheritDoc - */ - public $defaultSortField = 'time'; - - /** - * @inheritDoc - */ - public $defaultSortOrder = 'DESC'; - - /** - * @inheritDoc - */ - public $validSortFields = ['failureID', 'environment', 'userID', 'username', 'time', 'ipAddress', 'userAgent', 'validationError']; - - /** - * @inheritDoc - */ - public $objectListClassName = UserAuthenticationFailureList::class; - - /** - * @var string[] - * @since 5.4 - */ - public $filter = [ - 'environment' => '', - 'endDate' => '', - 'startDate' => '', - 'username' => '', - 'userAgent' => '', - 'validationError' => '', - ]; - - /** - * @inheritDoc - */ - public function readParameters() - { - parent::readParameters(); - - if (isset($_REQUEST['filter']) && \is_array($_REQUEST['filter'])) { - foreach ($_REQUEST['filter'] as $key => $value) { - if (\array_key_exists($key, $this->filter)) { - $this->filter[$key] = $value; - } - } - } - } - - /** - * @inheritDoc - */ - protected function initObjectList() + #[\Override] + protected function createGridViewController(): AbstractGridView { - parent::initObjectList(); - - if ($this->filter['environment'] !== '') { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.environment = ?', - [$this->filter['environment']] - ); - } - if ($this->filter['endDate'] !== '') { - $endDate = @\strtotime($this->filter['endDate']); - if ($endDate > 0) { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.time <= ?', - [$endDate] - ); - } - } - if ($this->filter['startDate'] !== '') { - $startDate = @\strtotime($this->filter['startDate']); - if ($startDate > 0) { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.time >= ?', - [$startDate] - ); - } - } - if ($this->filter['username'] !== '') { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.username LIKE ?', - ['%' . \addcslashes($this->filter['username'], '_%') . '%'] - ); - } - if ($this->filter['userAgent'] !== '') { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.userAgent LIKE ?', - ['%' . \addcslashes($this->filter['userAgent'], '_%') . '%'] - ); - } - if ($this->filter['validationError'] !== '') { - $this->objectList->getConditionBuilder()->add( - 'user_authentication_failure.validationError = ?', - [$this->filter['validationError']] - ); - } - } - - /** - * @inheritDoc - */ - public function assignVariables() - { - parent::assignVariables(); - - $filterLinkParameters = \http_build_query(['filter' => \array_filter($this->filter)], '', '&'); - - WCF::getTPL()->assign([ - 'filter' => $this->filter, - 'filterLinkParameters' => $filterLinkParameters ? '&' . $filterLinkParameters : '', - ]); + return new UserAuthenticationFailureGridView(); } } diff --git a/wcfsetup/install/files/lib/data/user/authentication/failure/UserAuthenticationFailure.class.php b/wcfsetup/install/files/lib/data/user/authentication/failure/UserAuthenticationFailure.class.php index 4c4e57ec6b3..f682ce3f8d2 100644 --- a/wcfsetup/install/files/lib/data/user/authentication/failure/UserAuthenticationFailure.class.php +++ b/wcfsetup/install/files/lib/data/user/authentication/failure/UserAuthenticationFailure.class.php @@ -20,6 +20,7 @@ * @property-read int $time timestamp at which the user authentication failure has occurred * @property-read string $ipAddress ip address of the user trying to login in * @property-read string $userAgent user agent of the user trying to login in + * @property-read string $validationError */ class UserAuthenticationFailure extends DatabaseObject { diff --git a/wcfsetup/install/files/lib/event/gridView/admin/UserAuthenticationFailureGridViewInitialized.class.php b/wcfsetup/install/files/lib/event/gridView/admin/UserAuthenticationFailureGridViewInitialized.class.php new file mode 100644 index 00000000000..921ed2a3613 --- /dev/null +++ b/wcfsetup/install/files/lib/event/gridView/admin/UserAuthenticationFailureGridViewInitialized.class.php @@ -0,0 +1,21 @@ + + * @since 6.2 + */ +final class UserAuthenticationFailureGridViewInitialized implements IPsr14Event +{ + public function __construct(public readonly UserAuthenticationFailureGridView $param) + { + } +} diff --git a/wcfsetup/install/files/lib/system/gridView/admin/UserAuthenticationFailureGridView.class.php b/wcfsetup/install/files/lib/system/gridView/admin/UserAuthenticationFailureGridView.class.php new file mode 100644 index 00000000000..343db14f35e --- /dev/null +++ b/wcfsetup/install/files/lib/system/gridView/admin/UserAuthenticationFailureGridView.class.php @@ -0,0 +1,132 @@ + + * @since 6.2 + */ +final class UserAuthenticationFailureGridView extends AbstractGridView +{ + public function __construct() + { + $this->addColumns([ + GridViewColumn::for("failureID") + ->label("wcf.global.objectID") + ->sortable() + ->renderer(new ObjectIdColumnRenderer()), + GridViewColumn::for("environment") + ->label("wcf.acp.user.authentication.failure.environment") + ->sortable() + ->filter( + new SelectFilter([ + 'user' => "wcf.acp.user.authentication.failure.environment.user", + 'admin' => "wcf.acp.user.authentication.failure.environment.admin", + ]) + ) + ->renderer( + new class extends DefaultColumnRenderer { + #[\Override] + public function render(mixed $value, DatabaseObject $row): string + { + \assert($row instanceof UserAuthenticationFailure); + + return WCF::getLanguage()->get( + "wcf.acp.user.authentication.failure.environment." . $row->environment + ); + } + } + ), + GridViewColumn::for("userID") + ->label("wcf.user.username") + ->titleColumn() + ->filter(new TextFilter()) + ->renderer(new UserLinkColumnRenderer(UserEditForm::class)) + ->sortable(), + GridViewColumn::for("time") + ->label("wcf.acp.user.authentication.failure.time") + ->filter(new TimeFilter()) + ->renderer(new TimeColumnRenderer()) + ->sortable(), + GridViewColumn::for("validationError") + ->label("wcf.acp.user.authentication.failure.validationError") + ->filter( + new SelectFilter([ + 'invalidPassword' => "wcf.acp.user.authentication.failure.validationError.invalidPassword", + "invalidUsername" => "wcf.acp.user.authentication.failure.validationError.invalidUsername", + ]) + ) + ->renderer( + new class extends DefaultColumnRenderer { + #[\Override] + public function render(mixed $value, DatabaseObject $row): string + { + \assert($row instanceof UserAuthenticationFailure); + + return WCF::getLanguage()->get( + "wcf.acp.user.authentication.failure.validationError." . $row->validationError + ); + } + } + ) + ->sortable(), + GridViewColumn::for("ipAddress") + ->label("wcf.user.ipAddress") + ->filter(new IpAddressFilter()) + ->renderer(new IpAddressColumnRenderer()) + ->sortable(), + GridViewColumn::for("userAgent") + ->label("wcf.user.userAgent") + ->renderer(new TruncatedTextColumnRenderer(75)) + ->filter(new TextFilter()) + ->sortable(), + ]); + + $this->setSortField("time"); + $this->setSortOrder("DESC"); + } + + #[\Override] + public function isAccessible(): bool + { + return \ENABLE_USER_AUTHENTICATION_FAILURE + && WCF::getSession()->getPermission('admin.management.canViewLog'); + } + + #[\Override] + protected function createObjectList(): DatabaseObjectList + { + return new UserAuthenticationFailureList(); + } + + #[\Override] + protected function getInitializedEvent(): ?IPsr14Event + { + return new UserAuthenticationFailureGridViewInitialized($this); + } +}