2016-03-28 08:26:48 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Body of LoginNotify extension
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @ingroup Extensions
|
|
|
|
*/
|
|
|
|
|
2017-06-15 22:56:12 +00:00
|
|
|
namespace LoginNotify;
|
|
|
|
|
|
|
|
use EchoAttributeManager;
|
2017-06-16 00:11:58 +00:00
|
|
|
use EchoEvent;
|
2016-07-06 22:06:27 +00:00
|
|
|
use MediaWiki\Auth\AuthenticationResponse;
|
2017-06-15 22:56:12 +00:00
|
|
|
use User;
|
2016-07-06 22:06:27 +00:00
|
|
|
|
2017-06-15 22:56:12 +00:00
|
|
|
class Hooks {
|
2016-03-28 08:26:48 +00:00
|
|
|
/**
|
|
|
|
* Add LoginNotify events to Echo
|
|
|
|
*
|
2017-03-23 03:28:30 +00:00
|
|
|
* @param string[] &$notifications Array of Echo notifications
|
|
|
|
* @param string[] &$notificationCategories Array of Echo notification categories
|
|
|
|
* @param string[] &$icons Array of icon details
|
2016-03-28 08:26:48 +00:00
|
|
|
* @return bool
|
|
|
|
*/
|
2016-04-26 16:24:19 +00:00
|
|
|
public static function onBeforeCreateEchoEvent(
|
2017-06-16 00:11:58 +00:00
|
|
|
array &$notifications,
|
|
|
|
array &$notificationCategories,
|
|
|
|
array &$icons
|
2016-04-26 16:24:19 +00:00
|
|
|
) {
|
2019-04-12 19:54:20 +00:00
|
|
|
global $wgLoginNotifyEnableOnSuccess, $wgNotifyTypeAvailabilityByCategory;
|
2016-03-28 08:26:48 +00:00
|
|
|
|
2017-03-17 20:26:31 +00:00
|
|
|
$icons['LoginNotify-user-avatar'] = [
|
|
|
|
'path' => 'LoginNotify/UserAvatar.svg'
|
2016-03-28 08:26:48 +00:00
|
|
|
];
|
|
|
|
|
2016-04-26 16:24:19 +00:00
|
|
|
$notificationCategories['login-fail'] = [
|
2016-03-28 08:26:48 +00:00
|
|
|
'priority' => 7,
|
|
|
|
'tooltip' => 'echo-pref-tooltip-login-fail',
|
2016-04-26 16:24:19 +00:00
|
|
|
];
|
2016-03-28 08:26:48 +00:00
|
|
|
|
|
|
|
$loginBase = [
|
|
|
|
EchoAttributeManager::ATTR_LOCATORS => [
|
|
|
|
'EchoUserLocator::locateEventAgent'
|
|
|
|
],
|
2018-10-27 00:37:23 +00:00
|
|
|
'canNotifyAgent' => true,
|
2016-03-28 08:26:48 +00:00
|
|
|
'category' => 'login-fail',
|
|
|
|
'group' => 'negative',
|
2017-06-27 18:08:12 +00:00
|
|
|
'presentation-model' => PresentationModel::class,
|
2017-06-22 01:16:06 +00:00
|
|
|
// fixme, what does this actually do?
|
|
|
|
'title-message' => 'loginnotify-login-fail',
|
|
|
|
'title-params' => [],
|
|
|
|
// FIXME Should count be a parameter
|
|
|
|
'email-subject-params' => [ 'agent', 'count' ],
|
|
|
|
'email-body-batch-params' => [ 'agent', 'count' ],
|
|
|
|
// FIXME is it ok not to set batch email messages, since
|
|
|
|
// we have immediate flag?
|
2017-03-17 20:26:31 +00:00
|
|
|
'icon' => 'LoginNotify-user-avatar',
|
2016-03-28 08:26:48 +00:00
|
|
|
'immediate' => true,
|
|
|
|
];
|
|
|
|
$notifications['login-fail-new'] = [
|
2017-04-07 21:48:57 +00:00
|
|
|
'bundle' => [
|
|
|
|
'web' => true,
|
|
|
|
'expandable' => false
|
|
|
|
]
|
2016-03-28 08:26:48 +00:00
|
|
|
] + $loginBase;
|
|
|
|
$notifications['login-fail-known'] = [
|
2017-04-07 21:48:57 +00:00
|
|
|
'bundle' => [
|
|
|
|
'web' => true,
|
|
|
|
'expandable' => false
|
|
|
|
]
|
2016-03-28 08:26:48 +00:00
|
|
|
] + $loginBase;
|
|
|
|
if ( $wgLoginNotifyEnableOnSuccess ) {
|
2016-04-26 16:24:19 +00:00
|
|
|
$notificationCategories['login-success'] = [
|
2016-03-28 08:26:48 +00:00
|
|
|
'priority' => 7,
|
|
|
|
'tooltip' => 'echo-pref-tooltip-login-success',
|
2016-04-26 16:24:19 +00:00
|
|
|
];
|
2016-03-28 08:26:48 +00:00
|
|
|
$notifications['login-success'] = [
|
|
|
|
'category' => 'login-success',
|
|
|
|
] + $loginBase;
|
2019-04-12 19:54:20 +00:00
|
|
|
$wgNotifyTypeAvailabilityByCategory['login-success'] = [
|
|
|
|
'web' => false,
|
|
|
|
'email' => true,
|
|
|
|
];
|
2016-03-28 08:26:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-06-16 00:11:58 +00:00
|
|
|
/**
|
|
|
|
* @param EchoEvent $event
|
2017-08-09 20:20:03 +00:00
|
|
|
* @param string &$bundleString
|
2017-06-16 00:11:58 +00:00
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public static function onEchoGetBundleRules( EchoEvent $event, &$bundleString ) {
|
2017-04-07 21:48:57 +00:00
|
|
|
switch ( $event->getType() ) {
|
|
|
|
case 'login-fail-new':
|
|
|
|
$bundleString = 'login-fail';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-28 08:26:48 +00:00
|
|
|
/**
|
2017-10-07 01:40:02 +00:00
|
|
|
* Hook for login auditing
|
2016-07-06 22:06:27 +00:00
|
|
|
*
|
2017-03-23 03:28:30 +00:00
|
|
|
* @param AuthenticationResponse $ret Is login successful?
|
|
|
|
* @param User|null $user User object on successful auth
|
|
|
|
* @param string $username Username for failed attempts.
|
2016-07-06 22:06:27 +00:00
|
|
|
*/
|
|
|
|
public static function onAuthManagerLoginAuthenticateAudit(
|
|
|
|
AuthenticationResponse $ret, $user, $username
|
|
|
|
) {
|
|
|
|
if ( $user ) {
|
|
|
|
$userObj = $user;
|
|
|
|
} else {
|
|
|
|
$userObj = User::newFromName( $username, 'usable' );
|
|
|
|
}
|
|
|
|
if ( !$userObj ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $ret->status === AuthenticationResponse::PASS ) {
|
|
|
|
self::doSuccessfulLogin( $userObj );
|
2018-05-07 16:32:37 +00:00
|
|
|
} elseif (
|
|
|
|
$ret->status === AuthenticationResponse::FAIL
|
|
|
|
&& $ret->message->getKey() !== 'login-throttled'
|
|
|
|
) {
|
2016-07-06 22:06:27 +00:00
|
|
|
self::doFailedLogin( $userObj );
|
|
|
|
}
|
|
|
|
// Other statuses include Abstain, Redirect, or UI. We ignore such
|
|
|
|
// statuses.
|
|
|
|
}
|
|
|
|
|
2017-03-23 03:28:30 +00:00
|
|
|
/**
|
|
|
|
* Handle a successful login (clear the attempt counter, send a notice, and record the
|
|
|
|
* current IP address as known).
|
|
|
|
*
|
|
|
|
* @param User $user The user who logged in.
|
|
|
|
*/
|
2018-01-01 22:22:04 +00:00
|
|
|
public static function doSuccessfulLogin( User $user ) {
|
2016-07-06 22:06:27 +00:00
|
|
|
$loginNotify = new LoginNotify();
|
|
|
|
$loginNotify->clearCounters( $user );
|
|
|
|
$loginNotify->sendSuccessNotice( $user );
|
|
|
|
$loginNotify->setCurrentAddressAsKnown( $user );
|
|
|
|
}
|
|
|
|
|
2017-03-23 03:28:30 +00:00
|
|
|
/**
|
|
|
|
* Handle a failed login (record the failure).
|
|
|
|
*
|
|
|
|
* @param User $user The user that failed to log in.
|
|
|
|
*/
|
2018-01-01 22:22:04 +00:00
|
|
|
public static function doFailedLogin( User $user ) {
|
2016-07-06 22:06:27 +00:00
|
|
|
$loginNotify = new LoginNotify();
|
|
|
|
$loginNotify->recordFailure( $user );
|
2016-03-28 08:26:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-10-07 01:40:02 +00:00
|
|
|
* Hook handler for new account creation.
|
2017-01-23 06:37:08 +00:00
|
|
|
*
|
|
|
|
* Called immediately after a local user has been created and saved to the database
|
|
|
|
*
|
|
|
|
* @todo This still sets cookies if user creates account well logged in as someone else.
|
|
|
|
* @param User $user User created
|
2017-08-09 20:20:03 +00:00
|
|
|
* @param bool $autocreated Whether this was an auto-created account
|
2017-01-23 06:37:08 +00:00
|
|
|
*/
|
|
|
|
public static function onLocalUserCreated( $user, $autocreated ) {
|
|
|
|
if ( !$autocreated ) {
|
|
|
|
$loginNotify = new LoginNotify();
|
|
|
|
$loginNotify->setCurrentAddressAsKnown( $user );
|
2016-03-28 08:26:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|