MediaWiki  1.34.4
OATHUserRepository.php
Go to the documentation of this file.
1 <?php
20 
22 use Psr\Log\LoggerInterface;
25 use FormatJson;
26 use CentralIdLookup;
27 use MWException;
28 use BagOStuff;
29 use ConfigException;
30 use User;
31 use stdClass;
32 use RequestContext;
33 
36  protected $lb;
37 
39  protected $cache;
40 
44  protected $auth;
45 
47  private $logger;
48 
56  $this->lb = $lb;
57  $this->cache = $cache;
58  $this->auth = $auth;
59 
60  $this->setLogger( LoggerFactory::getInstance( 'authentication' ) );
61  }
62 
66  public function setLogger( LoggerInterface $logger ) {
67  $this->logger = $logger;
68  }
69 
76  public function findByUser( User $user ) {
77  $oathUser = $this->cache->get( $user->getName() );
78  if ( !$oathUser ) {
79  $oathUser = new OATHUser( $user, null );
80 
81  $uid = CentralIdLookup::factory()->centralIdFromLocalUser( $user );
82  $res = $this->getDB( DB_REPLICA )->selectRow(
83  'oathauth_users',
84  '*',
85  [ 'id' => $uid ],
86  __METHOD__
87  );
88  if ( $res ) {
89  $data = $res->data;
90  $moduleKey = $res->module;
91  if ( $this->isLegacy( $res ) ) {
92  $module = $this->auth->getModuleByKey( 'totp' );
93  $data = $this->checkAndResolveLegacy( $data, $res );
94  } else {
95  $module = $this->auth->getModuleByKey( $moduleKey );
96  }
97  if ( $module === null ) {
98  // For sanity
99  throw new MWException( 'oathauth-module-invalid' );
100  }
101 
102  $oathUser->setModule( $module );
103  $decodedData = FormatJson::decode( $res->data, 1 );
104  if ( !isset( $decodedData['keys'] ) && $module->getName() === 'totp' ) {
105  // Legacy single-key setup
106  $key = $module->newKey( $decodedData );
107  $oathUser->addKey( $key );
108  } elseif ( is_array( $decodedData['keys'] ) ) {
109  foreach ( $decodedData['keys'] as $keyData ) {
110  $key = $module->newKey( $keyData );
111  $oathUser->addKey( $key );
112  }
113  }
114  }
115 
116  $this->cache->set( $user->getName(), $oathUser );
117  }
118  return $oathUser;
119  }
120 
127  public function persist( OATHUser $user, $clientInfo = null ) {
128  if ( !$clientInfo ) {
129  $clientInfo = RequestContext::getMain()->getRequest()->getIP();
130  }
131  $prevUser = $this->findByUser( $user->getUser() );
132  $data = $user->getModule()->getDataFromUser( $user );
133 
134  $this->getDB( DB_MASTER )->replace(
135  'oathauth_users',
136  [ 'id' ],
137  [
138  'id' => CentralIdLookup::factory()->centralIdFromLocalUser( $user->getUser() ),
139  'module' => $user->getModule()->getName(),
140  'data' => FormatJson::encode( $data )
141  ],
142  __METHOD__
143  );
144 
145  $userName = $user->getUser()->getName();
146  $this->cache->set( $userName, $user );
147 
148  if ( $prevUser !== false ) {
149  $this->logger->info( 'OATHAuth updated for {user} from {clientip}', [
150  'user' => $userName,
151  'clientip' => $clientInfo,
152  ] );
153  } else {
154  // If findByUser() has returned false, there was no user row or cache entry
155  $this->logger->info( 'OATHAuth enabled for {user} from {clientip}', [
156  'user' => $userName,
157  'clientip' => $clientInfo,
158  ] );
159  }
160  }
161 
166  public function remove( OATHUser $user, $clientInfo ) {
167  $this->getDB( DB_MASTER )->delete(
168  'oathauth_users',
169  [ 'id' => CentralIdLookup::factory()->centralIdFromLocalUser( $user->getUser() ) ],
170  __METHOD__
171  );
172 
173  $userName = $user->getUser()->getName();
174  $this->cache->delete( $userName );
175 
176  $this->logger->info( 'OATHAuth disabled for {user} from {clientip}', [
177  'user' => $userName,
178  'clientip' => $clientInfo,
179  ] );
180  }
181 
186  private function getDB( $index ) {
187  global $wgOATHAuthDatabase;
188 
189  return $this->lb->getConnectionRef( $index, [], $wgOATHAuthDatabase );
190  }
191 
196  private function isLegacy( $row ) {
197  if ( $row->module !== '' ) {
198  return false;
199  }
200  if ( property_exists( $row, 'secret' ) && $row->secret !== null ) {
201  return true;
202  }
203  return false;
204  }
205 
214  private function checkAndResolveLegacy( $data, $row ) {
215  if ( $data ) {
216  // New data exists - no action required
217  return $data;
218  }
219  if ( property_exists( $row, 'secret' ) && property_exists( $row, 'scratch_tokens' ) ) {
220  return FormatJson::encode( [
221  'secret' => $row->secret,
222  'scratch_tokens' => $row->scratch_tokens
223  ] );
224  }
225  return '';
226  }
227 }
MediaWiki\Extension\OATHAuth\OATHUserRepository\$cache
BagOStuff $cache
Definition: OATHUserRepository.php:39
MediaWiki\Extension\OATHAuth\OATHUser\getModule
getModule()
Gets the module instance associated with this user.
Definition: OATHUser.php:140
MediaWiki\Extension\OATHAuth\OATHUserRepository\findByUser
findByUser(User $user)
Definition: OATHUserRepository.php:76
MediaWiki\Extension\OATHAuth\OATHUserRepository\isLegacy
isLegacy( $row)
Definition: OATHUserRepository.php:196
MediaWiki\Extension\OATHAuth\OATHUser
Class representing a user from OATH's perspective.
Definition: OATHUser.php:28
MediaWiki\Extension\OATHAuth\OATHUserRepository\getDB
getDB( $index)
Definition: OATHUserRepository.php:186
MediaWiki\Logger\LoggerFactory\getInstance
static getInstance( $channel)
Get a named logger instance from the currently configured logger factory.
Definition: LoggerFactory.php:92
MediaWiki\Extension\OATHAuth\OATHUserRepository\$lb
ILoadBalancer $lb
Definition: OATHUserRepository.php:36
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:63
$res
$res
Definition: testCompression.php:52
MediaWiki\Extension\OATHAuth\OATHUserRepository
Definition: OATHUserRepository.php:34
FormatJson\decode
static decode( $value, $assoc=false)
Decodes a JSON string.
Definition: FormatJson.php:174
FormatJson\encode
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:115
FormatJson
JSON formatter wrapper class.
Definition: FormatJson.php:26
MWException
MediaWiki exception.
Definition: MWException.php:26
MediaWiki\Extension\OATHAuth\OATHAuth
Definition: OATHAuth.php:14
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
MediaWiki\Extension\OATHAuth\OATHUserRepository\setLogger
setLogger(LoggerInterface $logger)
Definition: OATHUserRepository.php:66
ConfigException
Exceptions for config failures.
Definition: ConfigException.php:28
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
RequestContext
Group all the pieces relevant to the context of a request into one instance.
Definition: RequestContext.php:33
DB_MASTER
const DB_MASTER
Definition: defines.php:26
MediaWiki\Extension\OATHAuth\OATHUserRepository\$logger
LoggerInterface $logger
Definition: OATHUserRepository.php:47
MediaWiki\Extension\OATHAuth\OATHUserRepository\$auth
OATHAuth $auth
Definition: OATHUserRepository.php:44
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:431
Wikimedia\Rdbms\DBConnRef
Helper class used for automatically marking an IDatabase connection as reusable (once it no longer ma...
Definition: DBConnRef.php:29
MediaWiki\Extension\OATHAuth
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
CentralIdLookup
The CentralIdLookup service allows for connecting local users with cluster-wide IDs.
Definition: CentralIdLookup.php:30
MediaWiki\Extension\OATHAuth\OATHUserRepository\checkAndResolveLegacy
checkAndResolveLegacy( $data, $row)
Checks if the DB data is in the new format, if not converts old data to new.
Definition: OATHUserRepository.php:214
MediaWiki\Extension\OATHAuth\OATHUser\getUser
getUser()
Definition: OATHUser.php:53
CentralIdLookup\factory
static factory( $providerId=null)
Fetch a CentralIdLookup.
Definition: CentralIdLookup.php:46
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:51
MediaWiki\Extension\OATHAuth\OATHUserRepository\__construct
__construct(ILoadBalancer $lb, BagOStuff $cache, OATHAuth $auth)
OATHUserRepository constructor.
Definition: OATHUserRepository.php:55
User\getName
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2364
MediaWiki\Extension\OATHAuth\OATHUserRepository\persist
persist(OATHUser $user, $clientInfo=null)
Definition: OATHUserRepository.php:127
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81