Use the new DatabaseVirtualDomains feature

Change-Id: I05b6361bd57ba6754bd308e04da1c635f95d042b
This commit is contained in:
Tim Starling 2023-10-26 14:44:54 +11:00
parent 70703bdce3
commit 6f32dafbc1
4 changed files with 25 additions and 75 deletions

View file

@ -7,25 +7,14 @@ The LoginNotify extension notifies you when someone logs into your account. It c
* Navigate to Special:Version on your wiki to verify that the extension is successfully installed.
#### Configuration parameters
"@doc": "The number of failed login attempts to permit from a known IP before a notification is triggered.",
"LoginNotifyAttemptsKnownIP": 10
"@doc": "The time-to-live of the count of failed login attempts from a known IP (from the time of the first failed attempt).",
"LoginNotifyExpiryKnownIP": 604800,
"@doc": "The number of failed login attempts to permit from a new IP before a notification is triggered.",
"LoginNotifyAttemptsNewIP": 3,
"@doc": "The time-to-live of the count of failed login attempts from a new IP (from the time of the first failed attempt).",
"LoginNotifyExpiryNewIP": 1209600,
"@doc": "Whether to trigger a notification after failed logins from known IPs.",
"LoginNotifyCheckKnownIPs": true,
"@doc": "Whether to trigger a notification after successful logins from unknown IPs.",
"LoginNotifyEnableOnSuccess": true,
"@doc": "Override this to use a different secret than $wgSecretKey",
"LoginNotifySecretKey": null,
"@doc": "Expiry in seconds. Default is 180 days",
"LoginNotifyCookieExpire": 15552000,
"@doc": "Override to allow sharing login cookies between sites on different subdomains",
"LoginNotifyCookieDomain": null,
"@doc": "Maximum number of users (records) to track as having successfully logged in on a particular device.",
"LoginNotifyMaxCookieRecords": 6,
"@doc": "Set to false to disable caching IPs in memcache. Set to 0 to cache forever. Default 60 days.",
"LoginNotifyCacheLoginIPExpiry": 5184000
See extension.json.
To place the loginnotify_seen_net table in a shared database, use
```php
$wgVirtualDomainsMapping['virtual-LoginNotify'] = [
'db' => '<shared database name>'
];
$wgLoginNotifyUseCentralId = true;
```

View file

@ -67,6 +67,9 @@
"ServiceWiringFiles": [
"includes/ServiceWiring.php"
],
"DatabaseVirtualDomains": [
"virtual-LoginNotify"
],
"config": {
"LoginNotifyAttemptsKnownIP": {
"description": "The number of failed login attempts to permit from a known IP before a notification is triggered.",
@ -112,14 +115,6 @@
"description": "Set to false to disable caching IPs in memcache. Set to 0 to cache forever. Default 60 days.",
"value": 5184000
},
"LoginNotifySeenDatabase": {
"description": "The database to store the loginnotify_seen_net table. This can be a shared database if CentralIdLookupProvider is configured to return a unique ID for the user.",
"value": null
},
"LoginNotifySeenCluster": {
"description": "The external cluster to store the loginnotify_seen_net table in. The default is to store it in the core database.",
"value": null
},
"LoginNotifyUseCheckUser": {
"description": "Use the CheckUser cu_changes table if it is available. This is redundant with LoginNotify's own table, available with MediaWiki 1.41. Setting this to true will be deprecated in a later release. Defaults to true temporarily during WMF pilot.",
"value": true
@ -128,6 +123,10 @@
"description": "Use the loginnotify_seen_net table. This is redundant with LoginNotifyUseCheckUser although both can be enabled during migration. Defaults to false temporarily during WMF pilot.",
"value": false
},
"LoginNotifyUseCentralId": {
"description": "Use central user IDs in the loginnotify_seen_net table. This should be set to true if the loginnotify_seen_net is in a shared database. CentralAuth should be installed and all users should be attached to it.",
"value": false
},
"LoginNotifySeenExpiry": {
"description": "The expiry time of data in the loginnotify_seen_net table, in seconds. This should be a multiple of LoginNotifyBucketSize. Default is 180 days.",
"value": 15552000

View file

@ -30,7 +30,6 @@ use WebRequest;
use Wikimedia\Assert\Assert;
use Wikimedia\IPUtils;
use Wikimedia\Rdbms\IDatabase;
use Wikimedia\Rdbms\ILoadBalancer;
use Wikimedia\Rdbms\IMaintainableDatabase;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\LBFactory;
@ -55,11 +54,10 @@ class LoginNotify implements LoggerAwareInterface {
'LoginNotifyMaxCookieRecords',
'LoginNotifySecretKey',
'LoginNotifySeenBucketSize',
'LoginNotifySeenCluster',
'LoginNotifySeenDatabase',
'LoginNotifySeenExpiry',
'LoginNotifyUseCheckUser',
'LoginNotifyUseSeenTable',
'LoginNotifyUseCentralId',
'SecretKey',
'UpdateRowsPerQuery'
];
@ -418,8 +416,7 @@ class LoginNotify implements LoggerAwareInterface {
* @return IReadableDatabase
*/
private function getSeenReplicaDb(): IReadableDatabase {
$dbName = $this->config->get( 'LoginNotifySeenDatabase' ) ?? false;
return $this->getSeenLoadBalancer()->getConnection( DB_REPLICA, [], $dbName );
return $this->lbFactory->getReplicaDatabase( 'virtual-LoginNotify' );
}
/**
@ -428,33 +425,7 @@ class LoginNotify implements LoggerAwareInterface {
* @return IDatabase
*/
private function getSeenPrimaryDb(): IDatabase {
$dbName = $this->config->get( 'LoginNotifySeenDatabase' ) ?? false;
return $this->getSeenLoadBalancer()->getConnection( DB_PRIMARY, [], $dbName );
}
/**
* Is the database holding the loginnotify_seen_net table replicated to
* multiple servers?
*
* @return bool
*/
private function isSeenDbReplicated() {
return $this->getSeenLoadBalancer()->hasReplicaServers();
}
/**
* Get the LoadBalancer holding the loginnotify_seen_net table.
*
* @return ILoadBalancer
*/
private function getSeenLoadBalancer() {
$cluster = $this->config->get( 'LoginNotifySeenCluster' );
if ( $cluster ) {
return $this->lbFactory->getExternalLB( $cluster );
} else {
$dbName = $this->config->get( 'LoginNotifySeenDatabase' ) ?? false;
return $this->lbFactory->getMainLB( $dbName );
}
return $this->lbFactory->getPrimaryDatabase( 'virtual-LoginNotify' );
}
/**
@ -497,7 +468,7 @@ class LoginNotify implements LoggerAwareInterface {
}
/**
* If LoginNotifySeenDatabase is configured, indicating a shared table,
* If LoginNotifyUseCentralId is true, indicating a shared table,
* get the central user ID. Otherwise, get the local user ID.
*
* If CentralAuth is not installed, $this->centralIdLookup will be a
@ -509,7 +480,7 @@ class LoginNotify implements LoggerAwareInterface {
* @return int
*/
private function getMaybeCentralId( User $user ) {
if ( ( $this->config->get( 'LoginNotifySeenDatabase' ) ?? false ) !== false ) {
if ( $this->config->get( 'LoginNotifyUseCentralId' ) ) {
return $this->centralIdLookup->centralIdFromLocalUser( $user );
} else {
return $user->getId();
@ -802,17 +773,9 @@ class LoginNotify implements LoggerAwareInterface {
// Insert a row
$dbw = $this->getSeenPrimaryDb();
$isReplicated = $this->isSeenDbReplicated();
$fname = __METHOD__;
$dbw->onTransactionCommitOrIdle(
function () use ( $dbw, $id, $hash, $isReplicated, $fname ) {
// Check if the user/hash is in the primary DB, as late as
// possible before the insert. (Trying to reduce the number of
// no-op queries in the binlog)
if ( $isReplicated && $this->userIsInCurrentSeenBucket( $id, $hash, true ) ) {
return;
}
function () use ( $dbw, $id, $hash, $fname ) {
$dbw->newInsertQueryBuilder()
->insert( 'loginnotify_seen_net' )
->ignore()

View file

@ -38,10 +38,9 @@ class LoginNotifyTest extends MediaWikiIntegrationTestCase {
"LoginNotifyCookieDomain" => null,
"LoginNotifyMaxCookieRecords" => 6,
"LoginNotifyCacheLoginIPExpiry" => 60 * $day,
'LoginNotifySeenCluster' => null,
"LoginNotifySeenDatabase" => null,
"LoginNotifyUseCheckUser" => false,
"LoginNotifyUseSeenTable" => true,
"LoginNotifyUseCentralId" => false,
"LoginNotifySeenExpiry" => 180 * $day,
"LoginNotifySeenBucketSize" => 15 * $day,
"UpdateRowsPerQuery" => 100,