Why: * When temporary accounts are known, the match patterns need to be available. If no match patterns are set, the match pattern is set to an array containing the generate pattern. Therefore the generate pattern must also be available if temporary accounts are known. * This was not the case before this commit, and certain settings caused an error to be thrown from isTempName. What: * Use the generate pattern for the match patterns if temp accounts are known and no match patterns are set. * Update the tests to use a generate pattern but no match pattern (the same as the default config). Change-Id: Iadfbed40b14378a9309e8d7afab6064e25480514
227 lines
6.1 KiB
PHP
227 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\User\TempUser;
|
|
|
|
use BadMethodCallException;
|
|
use InvalidArgumentException;
|
|
use MediaWiki\Permissions\Authority;
|
|
use MediaWiki\Utils\MWTimestamp;
|
|
use Wikimedia\Rdbms\IExpression;
|
|
use Wikimedia\Rdbms\IReadableDatabase;
|
|
|
|
/**
|
|
* The real TempUserConfig including internal methods used by TempUserCreator.
|
|
*
|
|
* @since 1.39
|
|
*/
|
|
class RealTempUserConfig implements TempUserConfig {
|
|
/** @var bool */
|
|
private $known = false;
|
|
|
|
/** @var bool */
|
|
private $enabled = false;
|
|
|
|
/** @var array */
|
|
private $serialProviderConfig = [];
|
|
|
|
/** @var array */
|
|
private $serialMappingConfig = [];
|
|
|
|
/** @var string[] */
|
|
private $autoCreateActions;
|
|
|
|
/** @var Pattern|null */
|
|
private $genPattern;
|
|
|
|
/** @var Pattern[]|null */
|
|
private $matchPatterns;
|
|
|
|
/** @var Pattern|null */
|
|
private $reservedPattern;
|
|
|
|
/** @var int|null */
|
|
private $expireAfterDays;
|
|
|
|
/** @var int|null */
|
|
private $notifyBeforeExpirationDays;
|
|
|
|
/**
|
|
* @param array $config See the documentation of $wgAutoCreateTempUser.
|
|
* - known: bool
|
|
* - enabled: bool
|
|
* - actions: array
|
|
* - genPattern: string
|
|
* - matchPattern: string|string[], optional
|
|
* - reservedPattern: string, optional
|
|
* - serialProvider: array
|
|
* - serialMapping: array
|
|
* - expireAfterDays: int, optional
|
|
* - notifyBeforeExpirationDays: int, optional
|
|
*/
|
|
public function __construct( $config ) {
|
|
$this->enabled = $config['enabled'] ?? false;
|
|
$this->known = $this->enabled || ( $config['known'] ?? false );
|
|
|
|
// Configuration related to creating new temporary accounts for some actions
|
|
if ( $this->enabled ) {
|
|
$this->autoCreateActions = $config['actions'];
|
|
$this->serialProviderConfig = $config['serialProvider'];
|
|
$this->serialMappingConfig = $config['serialMapping'];
|
|
}
|
|
|
|
// Configuration related to managing and identifying existing temporary accounts,
|
|
// regardless of whether new temp accounts are being actively created via the
|
|
// 'enabled' config flag.
|
|
if ( $this->known || $this->enabled ) {
|
|
$this->genPattern = new Pattern( 'genPattern', $config['genPattern'] );
|
|
$this->expireAfterDays = $config['expireAfterDays'] ?? null;
|
|
$this->notifyBeforeExpirationDays = $config['notifyBeforeExpirationDays'] ?? null;
|
|
if ( isset( $config['matchPattern'] ) ) {
|
|
$matchPatterns = $config['matchPattern'];
|
|
if ( !is_array( $config['matchPattern'] ) ) {
|
|
$matchPatterns = [ $matchPatterns ];
|
|
}
|
|
foreach ( $matchPatterns as &$pattern ) {
|
|
$pattern = new Pattern( 'matchPattern', $pattern );
|
|
}
|
|
$this->matchPatterns = $matchPatterns;
|
|
} else {
|
|
$this->matchPatterns = [ $this->genPattern ];
|
|
}
|
|
}
|
|
|
|
// Configuration that is set regardless of whether the feature is enabled or known.
|
|
if ( isset( $config['reservedPattern'] ) ) {
|
|
$this->reservedPattern = new Pattern( 'reservedPattern', $config['reservedPattern'] );
|
|
}
|
|
}
|
|
|
|
public function isEnabled() {
|
|
return $this->enabled;
|
|
}
|
|
|
|
public function isKnown() {
|
|
return $this->known;
|
|
}
|
|
|
|
public function isAutoCreateAction( string $action ) {
|
|
if ( $action === 'create' ) {
|
|
$action = 'edit';
|
|
}
|
|
return $this->isEnabled()
|
|
&& in_array( $action, $this->autoCreateActions, true );
|
|
}
|
|
|
|
public function shouldAutoCreate( Authority $authority, string $action ) {
|
|
return $this->isAutoCreateAction( $action )
|
|
&& !$authority->isRegistered()
|
|
&& $authority->isAllowed( 'createaccount' );
|
|
}
|
|
|
|
public function isTempName( string $name ) {
|
|
if ( !$this->isKnown() ) {
|
|
return false;
|
|
}
|
|
foreach ( $this->matchPatterns as $pattern ) {
|
|
if ( $pattern->isMatch( $name ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function isReservedName( string $name ) {
|
|
return $this->isTempName( $name ) || ( $this->reservedPattern && $this->reservedPattern->isMatch( $name ) );
|
|
}
|
|
|
|
public function getPlaceholderName(): string {
|
|
$year = null;
|
|
if ( $this->serialProviderConfig['useYear'] ?? false ) {
|
|
$year = MWTimestamp::getInstance()->format( 'Y' );
|
|
}
|
|
if ( $this->isEnabled() ) {
|
|
return $this->genPattern->generate( '*', $year );
|
|
} else {
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated since 1.42.
|
|
*/
|
|
public function getMatchPattern(): Pattern {
|
|
wfDeprecated( __METHOD__, '1.42' );
|
|
if ( $this->isKnown() ) {
|
|
// This method is deprecated to allow time for callers to update.
|
|
// This method only returns one Pattern, so just return the first one.
|
|
return $this->getMatchPatterns()[0];
|
|
} else {
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
}
|
|
}
|
|
|
|
public function getMatchPatterns(): array {
|
|
if ( $this->isKnown() ) {
|
|
return $this->matchPatterns;
|
|
} else {
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
}
|
|
}
|
|
|
|
public function getMatchCondition( IReadableDatabase $db, string $field, string $op ): IExpression {
|
|
if ( $this->isKnown() ) {
|
|
$exprs = [];
|
|
foreach ( $this->getMatchPatterns() as $pattern ) {
|
|
$exprs[] = $db->expr( $field, $op, $pattern->toLikeValue( $db ) );
|
|
}
|
|
if ( count( $exprs ) === 1 ) {
|
|
return $exprs[0];
|
|
}
|
|
if ( $op === IExpression::LIKE ) {
|
|
return $db->orExpr( $exprs );
|
|
} elseif ( $op === IExpression::NOT_LIKE ) {
|
|
return $db->andExpr( $exprs );
|
|
} else {
|
|
throw new InvalidArgumentException( "Invalid operator $op" );
|
|
}
|
|
} else {
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
}
|
|
}
|
|
|
|
public function getExpireAfterDays(): ?int {
|
|
return $this->expireAfterDays;
|
|
}
|
|
|
|
public function getNotifyBeforeExpirationDays(): ?int {
|
|
return $this->notifyBeforeExpirationDays;
|
|
}
|
|
|
|
/**
|
|
* @internal For TempUserCreator only
|
|
* @return Pattern
|
|
*/
|
|
public function getGeneratorPattern(): Pattern {
|
|
if ( $this->isEnabled() ) {
|
|
return $this->genPattern;
|
|
} else {
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal For TempUserCreator only
|
|
* @return array
|
|
*/
|
|
public function getSerialProviderConfig(): array {
|
|
return $this->serialProviderConfig;
|
|
}
|
|
|
|
/**
|
|
* @internal For TempUserCreator only
|
|
* @return array
|
|
*/
|
|
public function getSerialMappingConfig(): array {
|
|
return $this->serialMappingConfig;
|
|
}
|
|
}
|