3 * MediaWiki session info
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
24 namespace MediaWiki\Session
;
27 * Value object returned by SessionProvider
29 * This holds the data necessary to construct a Session.
35 /** Minimum allowed priority */
36 const MIN_PRIORITY
= 1;
38 /** Maximum allowed priority */
39 const MAX_PRIORITY
= 100;
41 /** @var SessionProvider|null */
50 /** @var UserInfo|null */
51 private $userInfo = null;
53 private $persisted = false;
54 private $remembered = false;
55 private $forceHTTPS = false;
56 private $idIsSafe = false;
57 private $forceUse = false;
59 /** @var array|null */
60 private $providerMetadata = null;
63 * @param int $priority Session priority
65 * - provider: (SessionProvider|null) If not given, the provider will be
66 * determined from the saved session data.
67 * - id: (string|null) Session ID
68 * - userInfo: (UserInfo|null) User known from the request. If
69 * $provider->canChangeUser() is false, a verified user
71 * - persisted: (bool) Whether this session was persisted
72 * - remembered: (bool) Whether the verified user was remembered.
74 * - forceHTTPS: (bool) Whether to force HTTPS for this session
75 * - metadata: (array) Provider metadata, to be returned by
76 * Session::getProviderMetadata(). See SessionProvider::mergeMetadata()
77 * and SessionProvider::refreshSessionInfo().
78 * - idIsSafe: (bool) Set true if the 'id' did not come from the user.
79 * Generally you'll use this from SessionProvider::newEmptySession(),
80 * and not from any other method.
81 * - forceUse: (bool) Set true if the 'id' is from
82 * SessionProvider::hashToSessionId() to delete conflicting session
83 * store data instead of discarding this SessionInfo. Ignored unless
84 * both 'provider' and 'id' are given.
85 * - copyFrom: (SessionInfo) SessionInfo to copy other data items from.
87 public function __construct( $priority, array $data ) {
88 if ( $priority < self
::MIN_PRIORITY ||
$priority > self
::MAX_PRIORITY
) {
89 throw new \
InvalidArgumentException( 'Invalid priority' );
92 if ( isset( $data['copyFrom'] ) ) {
93 $from = $data['copyFrom'];
94 if ( !$from instanceof SessionInfo
) {
95 throw new \
InvalidArgumentException( 'Invalid copyFrom' );
98 'provider' => $from->provider
,
100 'userInfo' => $from->userInfo
,
101 'persisted' => $from->persisted
,
102 'remembered' => $from->remembered
,
103 'forceHTTPS' => $from->forceHTTPS
,
104 'metadata' => $from->providerMetadata
,
105 'idIsSafe' => $from->idIsSafe
,
106 'forceUse' => $from->forceUse
,
107 // @codeCoverageIgnoreStart
109 // @codeCoverageIgnoreEnd
115 'persisted' => false,
116 'remembered' => true,
117 'forceHTTPS' => false,
121 // @codeCoverageIgnoreStart
123 // @codeCoverageIgnoreEnd
126 if ( $data['id'] !== null && !SessionManager
::validateSessionId( $data['id'] ) ) {
127 throw new \
InvalidArgumentException( 'Invalid session ID' );
130 if ( $data['userInfo'] !== null && !$data['userInfo'] instanceof UserInfo
) {
131 throw new \
InvalidArgumentException( 'Invalid userInfo' );
134 if ( !$data['provider'] && $data['id'] === null ) {
135 throw new \
InvalidArgumentException(
136 'Must supply an ID when no provider is given'
140 if ( $data['metadata'] !== null && !is_array( $data['metadata'] ) ) {
141 throw new \
InvalidArgumentException( 'Invalid metadata' );
144 $this->provider
= $data['provider'];
145 if ( $data['id'] !== null ) {
146 $this->id
= $data['id'];
147 $this->idIsSafe
= $data['idIsSafe'];
148 $this->forceUse
= $data['forceUse'] && $this->provider
;
150 $this->id
= $this->provider
->getManager()->generateSessionId();
151 $this->idIsSafe
= true;
152 $this->forceUse
= false;
154 $this->priority
= (int)$priority;
155 $this->userInfo
= $data['userInfo'];
156 $this->persisted
= (bool)$data['persisted'];
157 if ( $data['provider'] !== null ) {
158 if ( $this->userInfo
!== null && !$this->userInfo
->isAnon() && $this->userInfo
->isVerified() ) {
159 $this->remembered
= (bool)$data['remembered'];
161 $this->providerMetadata
= $data['metadata'];
163 $this->forceHTTPS
= (bool)$data['forceHTTPS'];
167 * Return the provider
168 * @return SessionProvider|null
170 final public function getProvider() {
171 return $this->provider
;
175 * Return the session ID
178 final public function getId() {
183 * Indicate whether the ID is "safe"
185 * The ID is safe in the following cases:
186 * - The ID was randomly generated by the constructor.
187 * - The ID was found in the backend data store.
188 * - $this->getProvider()->persistsSessionId() is false.
189 * - The constructor was explicitly told it's safe using the 'idIsSafe'
194 final public function isIdSafe() {
195 return $this->idIsSafe
;
199 * Force use of this SessionInfo if validation fails
201 * The normal behavior is to discard the SessionInfo if validation against
202 * the data stored in the session store fails. If this returns true,
203 * SessionManager will instead delete the session store data so this
204 * SessionInfo may still be used. This is important for providers which use
205 * deterministic IDs and so cannot just generate a random new one.
209 final public function forceUse() {
210 return $this->forceUse
;
214 * Return the priority
217 final public function getPriority() {
218 return $this->priority
;
223 * @return UserInfo|null
225 final public function getUserInfo() {
226 return $this->userInfo
;
230 * Return whether the session is persisted
233 final public function wasPersisted() {
234 return $this->persisted
;
238 * Return provider metadata
241 final public function getProviderMetadata() {
242 return $this->providerMetadata
;
246 * Return whether the user was remembered
248 * For providers that can persist the user separately from the session,
249 * the human using it may not actually *want* that to be done. For example,
250 * a cookie-based provider can set cookies that are longer-lived than the
251 * backend session data, but on a public terminal the human likely doesn't
252 * want those cookies set.
254 * This is false unless a non-anonymous verified user was passed to
255 * the SessionInfo constructor by the provider, and the provider didn't
256 * pass false for the 'remembered' data item.
260 final public function wasRemembered() {
261 return $this->remembered
;
265 * Whether this session should only be used over HTTPS
268 final public function forceHTTPS() {
269 return $this->forceHTTPS
;
272 public function __toString() {
273 return '[' . $this->getPriority() . ']' .
274 ( $this->getProvider() ?
: 'null' ) .
275 ( $this->userInfo ?
: '<null>' ) . $this->getId();
279 * Compare two SessionInfo objects by priority
280 * @param SessionInfo $a
281 * @param SessionInfo $b
282 * @return int Negative if $a < $b, positive if $a > $b, zero if equal
284 public static function compare( $a, $b ) {
285 return $a->getPriority() - $b->getPriority();