2022-02-28 03:05:58 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MediaWiki\User\TempUser;
|
|
|
|
|
|
2023-01-22 00:55:59 +00:00
|
|
|
use BadMethodCallException;
|
2024-03-01 23:31:21 +00:00
|
|
|
use InvalidArgumentException;
|
2023-05-12 03:44:11 +00:00
|
|
|
use MediaWiki\Permissions\Authority;
|
2024-03-26 15:04:36 +00:00
|
|
|
use MediaWiki\Utils\MWTimestamp;
|
2024-03-01 23:31:21 +00:00
|
|
|
use Wikimedia\Rdbms\IExpression;
|
|
|
|
|
use Wikimedia\Rdbms\IReadableDatabase;
|
2022-02-28 03:05:58 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The real TempUserConfig including internal methods used by TempUserCreator.
|
|
|
|
|
*
|
|
|
|
|
* @since 1.39
|
|
|
|
|
*/
|
|
|
|
|
class RealTempUserConfig implements TempUserConfig {
|
2024-06-07 12:15:56 +00:00
|
|
|
/** @var bool */
|
|
|
|
|
private $known = false;
|
|
|
|
|
|
2022-02-28 03:05:58 +00:00
|
|
|
/** @var bool */
|
|
|
|
|
private $enabled = false;
|
|
|
|
|
|
|
|
|
|
/** @var array */
|
|
|
|
|
private $serialProviderConfig = [];
|
|
|
|
|
|
|
|
|
|
/** @var array */
|
|
|
|
|
private $serialMappingConfig = [];
|
|
|
|
|
|
|
|
|
|
/** @var string[] */
|
|
|
|
|
private $autoCreateActions;
|
|
|
|
|
|
|
|
|
|
/** @var Pattern|null */
|
|
|
|
|
private $genPattern;
|
|
|
|
|
|
2024-01-10 23:40:27 +00:00
|
|
|
/** @var Pattern[]|null */
|
|
|
|
|
private $matchPatterns;
|
2022-02-28 03:05:58 +00:00
|
|
|
|
2023-03-14 05:11:17 +00:00
|
|
|
/** @var Pattern|null */
|
|
|
|
|
private $reservedPattern;
|
|
|
|
|
|
2023-08-23 12:06:00 +00:00
|
|
|
/** @var int|null */
|
|
|
|
|
private $expireAfterDays;
|
|
|
|
|
|
2023-08-31 11:11:18 +00:00
|
|
|
/** @var int|null */
|
|
|
|
|
private $notifyBeforeExpirationDays;
|
|
|
|
|
|
2022-02-28 03:05:58 +00:00
|
|
|
/**
|
|
|
|
|
* @param array $config See the documentation of $wgAutoCreateTempUser.
|
2024-06-07 12:15:56 +00:00
|
|
|
* - known: bool
|
2022-02-28 03:05:58 +00:00
|
|
|
* - enabled: bool
|
|
|
|
|
* - actions: array
|
|
|
|
|
* - genPattern: string
|
2024-01-10 23:40:27 +00:00
|
|
|
* - matchPattern: string|string[], optional
|
2023-03-14 05:11:17 +00:00
|
|
|
* - reservedPattern: string, optional
|
2022-02-28 03:05:58 +00:00
|
|
|
* - serialProvider: array
|
|
|
|
|
* - serialMapping: array
|
2023-08-23 12:06:00 +00:00
|
|
|
* - expireAfterDays: int, optional
|
2023-08-31 11:11:18 +00:00
|
|
|
* - notifyBeforeExpirationDays: int, optional
|
2022-02-28 03:05:58 +00:00
|
|
|
*/
|
|
|
|
|
public function __construct( $config ) {
|
2024-06-07 12:15:56 +00:00
|
|
|
$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 ) {
|
2022-02-28 03:05:58 +00:00
|
|
|
$this->autoCreateActions = $config['actions'];
|
2024-06-07 12:15:56 +00:00
|
|
|
$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 ) {
|
2024-07-19 14:00:44 +00:00
|
|
|
$this->genPattern = new Pattern( 'genPattern', $config['genPattern'] );
|
2024-06-07 12:15:56 +00:00
|
|
|
$this->expireAfterDays = $config['expireAfterDays'] ?? null;
|
|
|
|
|
$this->notifyBeforeExpirationDays = $config['notifyBeforeExpirationDays'] ?? null;
|
2022-02-28 03:05:58 +00:00
|
|
|
if ( isset( $config['matchPattern'] ) ) {
|
2024-01-10 23:40:27 +00:00
|
|
|
$matchPatterns = $config['matchPattern'];
|
|
|
|
|
if ( !is_array( $config['matchPattern'] ) ) {
|
|
|
|
|
$matchPatterns = [ $matchPatterns ];
|
|
|
|
|
}
|
|
|
|
|
foreach ( $matchPatterns as &$pattern ) {
|
|
|
|
|
$pattern = new Pattern( 'matchPattern', $pattern );
|
|
|
|
|
}
|
|
|
|
|
$this->matchPatterns = $matchPatterns;
|
2022-02-28 03:05:58 +00:00
|
|
|
} else {
|
2024-01-10 23:40:27 +00:00
|
|
|
$this->matchPatterns = [ $this->genPattern ];
|
2022-02-28 03:05:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-06-07 12:15:56 +00:00
|
|
|
|
|
|
|
|
// Configuration that is set regardless of whether the feature is enabled or known.
|
2023-03-14 05:11:17 +00:00
|
|
|
if ( isset( $config['reservedPattern'] ) ) {
|
|
|
|
|
$this->reservedPattern = new Pattern( 'reservedPattern', $config['reservedPattern'] );
|
|
|
|
|
}
|
2022-02-28 03:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
2022-05-05 12:32:57 +00:00
|
|
|
public function isEnabled() {
|
|
|
|
|
return $this->enabled;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 12:15:56 +00:00
|
|
|
public function isKnown() {
|
|
|
|
|
return $this->known;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-28 03:05:58 +00:00
|
|
|
public function isAutoCreateAction( string $action ) {
|
|
|
|
|
if ( $action === 'create' ) {
|
|
|
|
|
$action = 'edit';
|
|
|
|
|
}
|
2024-01-17 17:02:06 +00:00
|
|
|
return $this->isEnabled()
|
2022-02-28 03:05:58 +00:00
|
|
|
&& in_array( $action, $this->autoCreateActions, true );
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-12 03:44:11 +00:00
|
|
|
public function shouldAutoCreate( Authority $authority, string $action ) {
|
|
|
|
|
return $this->isAutoCreateAction( $action )
|
|
|
|
|
&& !$authority->isRegistered()
|
|
|
|
|
&& $authority->isAllowed( 'createaccount' );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-14 05:11:17 +00:00
|
|
|
public function isTempName( string $name ) {
|
2024-06-07 12:15:56 +00:00
|
|
|
if ( !$this->isKnown() ) {
|
2024-01-10 23:40:27 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
foreach ( $this->matchPatterns as $pattern ) {
|
|
|
|
|
if ( $pattern->isMatch( $name ) ) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2022-02-28 03:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-14 05:11:17 +00:00
|
|
|
public function isReservedName( string $name ) {
|
2024-01-10 23:40:27 +00:00
|
|
|
return $this->isTempName( $name ) || ( $this->reservedPattern && $this->reservedPattern->isMatch( $name ) );
|
2023-03-14 05:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
2022-02-28 03:05:58 +00:00
|
|
|
public function getPlaceholderName(): string {
|
2024-03-26 15:04:36 +00:00
|
|
|
$year = null;
|
|
|
|
|
if ( $this->serialProviderConfig['useYear'] ?? false ) {
|
|
|
|
|
$year = MWTimestamp::getInstance()->format( 'Y' );
|
|
|
|
|
}
|
2024-01-10 23:40:27 +00:00
|
|
|
if ( $this->isEnabled() ) {
|
2024-03-26 15:04:36 +00:00
|
|
|
return $this->genPattern->generate( '*', $year );
|
2022-02-28 03:05:58 +00:00
|
|
|
} else {
|
2023-01-22 00:55:59 +00:00
|
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
2022-02-28 03:05:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-26 00:08:13 +00:00
|
|
|
/**
|
|
|
|
|
* @deprecated since 1.42.
|
|
|
|
|
*/
|
2023-08-02 13:27:41 +00:00
|
|
|
public function getMatchPattern(): Pattern {
|
2024-01-18 20:08:45 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.42' );
|
2024-06-07 12:15:56 +00:00
|
|
|
if ( $this->isKnown() ) {
|
2024-01-10 23:40:27 +00:00
|
|
|
// 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 {
|
2024-06-07 12:15:56 +00:00
|
|
|
if ( $this->isKnown() ) {
|
2024-01-10 23:40:27 +00:00
|
|
|
return $this->matchPatterns;
|
2023-08-02 13:27:41 +00:00
|
|
|
} else {
|
|
|
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-01 23:31:21 +00:00
|
|
|
public function getMatchCondition( IReadableDatabase $db, string $field, string $op ): IExpression {
|
2024-06-07 12:15:56 +00:00
|
|
|
if ( $this->isKnown() ) {
|
2024-03-01 23:31:21 +00:00
|
|
|
$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 ) {
|
2024-06-29 20:31:02 +00:00
|
|
|
return $db->orExpr( $exprs );
|
2024-03-01 23:31:21 +00:00
|
|
|
} elseif ( $op === IExpression::NOT_LIKE ) {
|
2024-06-29 20:31:02 +00:00
|
|
|
return $db->andExpr( $exprs );
|
2024-03-01 23:31:21 +00:00
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException( "Invalid operator $op" );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-23 12:06:00 +00:00
|
|
|
public function getExpireAfterDays(): ?int {
|
|
|
|
|
return $this->expireAfterDays;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-31 11:11:18 +00:00
|
|
|
public function getNotifyBeforeExpirationDays(): ?int {
|
|
|
|
|
return $this->notifyBeforeExpirationDays;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-28 03:05:58 +00:00
|
|
|
/**
|
|
|
|
|
* @internal For TempUserCreator only
|
|
|
|
|
* @return Pattern
|
|
|
|
|
*/
|
|
|
|
|
public function getGeneratorPattern(): Pattern {
|
2024-01-10 23:40:27 +00:00
|
|
|
if ( $this->isEnabled() ) {
|
2022-02-28 03:05:58 +00:00
|
|
|
return $this->genPattern;
|
|
|
|
|
} else {
|
2023-01-22 00:55:59 +00:00
|
|
|
throw new BadMethodCallException( __METHOD__ . ' is disabled' );
|
2022-02-28 03:05:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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;
|
|
|
|
|
}
|
|
|
|
|
}
|