MediaWiki  master
BotPasswordSessionProvider.php
Go to the documentation of this file.
1 <?php
25 
26 use BotPassword;
29 use User;
30 use WebRequest;
31 
38  private $grantsInfo;
39 
41  private $isApiRequest;
42 
51  public function __construct( GrantsInfo $grantsInfo, array $params = [] ) {
52  if ( !isset( $params['sessionCookieName'] ) ) {
53  $params['sessionCookieName'] = '_BPsession';
54  }
55  parent::__construct( $params );
56 
57  if ( !isset( $params['priority'] ) ) {
58  throw new \InvalidArgumentException( __METHOD__ . ': priority must be specified' );
59  }
60  if ( $params['priority'] < SessionInfo::MIN_PRIORITY ||
61  $params['priority'] > SessionInfo::MAX_PRIORITY
62  ) {
63  throw new \InvalidArgumentException( __METHOD__ . ': Invalid priority' );
64  }
65 
66  $this->priority = $params['priority'];
67 
68  $this->grantsInfo = $grantsInfo;
69 
70  $this->isApiRequest = $params['isApiRequest']
71  ?? ( defined( 'MW_API' ) || defined( 'MW_REST_API' ) );
72  }
73 
74  public function provideSessionInfo( WebRequest $request ) {
75  // Only relevant for the (Action or REST) API
76  if ( !$this->isApiRequest ) {
77  return null;
78  }
79 
80  // Enabled?
81  if ( !$this->getConfig()->get( MainConfigNames::EnableBotPasswords ) ) {
82  return null;
83  }
84 
85  // Have a session ID?
86  $id = $this->getSessionIdFromCookie( $request );
87  if ( $id === null ) {
88  return null;
89  }
90 
91  return new SessionInfo( $this->priority, [
92  'provider' => $this,
93  'id' => $id,
94  'persisted' => true
95  ] );
96  }
97 
98  public function newSessionInfo( $id = null ) {
99  // We don't activate by default
100  return null;
101  }
102 
110  public function newSessionForRequest( User $user, BotPassword $bp, WebRequest $request ) {
111  $id = $this->getSessionIdFromCookie( $request );
112  $info = new SessionInfo( SessionInfo::MAX_PRIORITY, [
113  'provider' => $this,
114  'id' => $id,
115  'userInfo' => UserInfo::newFromUser( $user, true ),
116  'persisted' => $id !== null,
117  'metadata' => [
118  'centralId' => $bp->getUserCentralId(),
119  'appId' => $bp->getAppId(),
120  'token' => $bp->getToken(),
121  'rights' => $this->grantsInfo->getGrantRights( $bp->getGrants() ),
122  ],
123  ] );
124  $session = $this->getManager()->getSessionFromInfo( $info, $request );
125  $session->persist();
126  return $session;
127  }
128 
133  public function refreshSessionInfo( SessionInfo $info, WebRequest $request, &$metadata ) {
134  $missingKeys = array_diff(
135  [ 'centralId', 'appId', 'token' ],
136  array_keys( $metadata )
137  );
138  if ( $missingKeys ) {
139  $this->logger->info( 'Session "{session}": Missing metadata: {missing}', [
140  'session' => $info->__toString(),
141  'missing' => implode( ', ', $missingKeys ),
142  ] );
143  return false;
144  }
145 
146  $bp = BotPassword::newFromCentralId( $metadata['centralId'], $metadata['appId'] );
147  if ( !$bp ) {
148  $this->logger->info(
149  'Session "{session}": No BotPassword for {centralId} {appId}',
150  [
151  'session' => $info->__toString(),
152  'centralId' => $metadata['centralId'],
153  'appId' => $metadata['appId'],
154  ] );
155  return false;
156  }
157 
158  if ( !hash_equals( $metadata['token'], $bp->getToken() ) ) {
159  $this->logger->info( 'Session "{session}": BotPassword token check failed', [
160  'session' => $info->__toString(),
161  'centralId' => $metadata['centralId'],
162  'appId' => $metadata['appId'],
163  ] );
164  return false;
165  }
166 
167  $status = $bp->getRestrictions()->check( $request );
168  if ( !$status->isOK() ) {
169  $this->logger->info(
170  'Session "{session}": Restrictions check failed',
171  [
172  'session' => $info->__toString(),
173  'restrictions' => $status->getValue(),
174  'centralId' => $metadata['centralId'],
175  'appId' => $metadata['appId'],
176  ] );
177  return false;
178  }
179 
180  // Update saved rights
181  $metadata['rights'] = $this->grantsInfo->getGrantRights( $bp->getGrants() );
182 
183  return true;
184  }
185 
190  public function preventSessionsForUser( $username ) {
192  }
193 
194  public function getAllowedUserRights( SessionBackend $backend ) {
195  if ( $backend->getProvider() !== $this ) {
196  throw new \InvalidArgumentException( 'Backend\'s provider isn\'t $this' );
197  }
198  $data = $backend->getProviderMetadata();
199  if ( $data && isset( $data['rights'] ) && is_array( $data['rights'] ) ) {
200  return $data['rights'];
201  }
202 
203  // Should never happen
204  $this->logger->debug( __METHOD__ . ': No provider metadata, returning no rights allowed' );
205  return [];
206  }
207 }
Utility class for bot passwords.
Definition: BotPassword.php:34
getUserCentralId()
Get the central user ID.
static newFromCentralId( $centralId, $appId, $flags=self::READ_NORMAL)
Load a BotPassword from the database.
static removeAllPasswordsForUser( $username)
Remove all passwords for a user, by name.
A class containing constants representing the names of configuration variables.
const EnableBotPasswords
Name constant for the EnableBotPasswords setting, for use with Config::get()
Users can authorize applications to use their account via OAuth.
Definition: GrantsInfo.php:33
newSessionForRequest(User $user, BotPassword $bp, WebRequest $request)
Create a new session for a request.
provideSessionInfo(WebRequest $request)
Provide session info for a request.
__construct(GrantsInfo $grantsInfo, array $params=[])
preventSessionsForUser( $username)
Prevent future sessions for the user.If the provider is capable of returning a SessionInfo with a ver...
getAllowedUserRights(SessionBackend $backend)
Fetch the rights allowed the user when the specified session is active.
newSessionInfo( $id=null)
Provide session info for a new, empty session.
refreshSessionInfo(SessionInfo $info, WebRequest $request, &$metadata)
Validate a loaded SessionInfo and refresh provider metadata.This is similar in purpose to the 'Sessio...
An ImmutableSessionProviderWithCookie doesn't persist the user, but optionally can use a cookie to su...
getSessionIdFromCookie(WebRequest $request)
Get the session ID from the cookie, if any.
This is the actual workhorse for Session.
getProviderMetadata()
Fetch provider metadata.
getProvider()
Fetch the SessionProvider for this session.
Value object returned by SessionProvider.
Definition: SessionInfo.php:37
const MIN_PRIORITY
Minimum allowed priority.
Definition: SessionInfo.php:39
const MAX_PRIORITY
Maximum allowed priority.
Definition: SessionInfo.php:42
getManager()
Get the session manager.
static newFromUser(User $user, $verified=false)
Create an instance from an existing User object.
Definition: UserInfo.php:123
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:70
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:47