summaryrefslogtreecommitdiff
path: root/www/wiki/includes/session/UserInfo.php
blob: c01b9eca9d4ed3eb030ca53cc3bacdf4be72100a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<?php
/**
 * MediaWiki session user info
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @ingroup Session
 */

namespace MediaWiki\Session;

use User;

/**
 * Object holding data about a session's user
 *
 * In general, this class exists for two purposes:
 * - User doesn't distinguish between "anonymous user" and "non-anonymous user
 *   that doesn't exist locally", while we do need to.
 * - We also need the "verified" property described below; tracking it via
 *   another data item to SessionInfo's constructor makes things much more
 *   confusing.
 *
 * A UserInfo may be "verified". This indicates that the creator knows that the
 * request really comes from that user, whether that's by validating OAuth
 * credentials, SSL client certificates, or by having both the user ID and
 * token available from cookies.
 *
 * An "unverified" UserInfo should be used when it's not possible to
 * authenticate the user, e.g. the user ID cookie is set but the user Token
 * cookie isn't. If the Token is available but doesn't match, don't return a
 * UserInfo at all.
 *
 * @ingroup Session
 * @since 1.27
 */
final class UserInfo {
	private $verified = false;

	/** @var User|null */
	private $user = null;

	private function __construct( User $user = null, $verified ) {
		if ( $user && $user->isAnon() && !User::isUsableName( $user->getName() ) ) {
			$this->verified = true;
			$this->user = null;
		} else {
			$this->verified = $verified;
			$this->user = $user;
		}
	}

	/**
	 * Create an instance for an anonymous (i.e. not logged in) user
	 *
	 * Logged-out users are always "verified".
	 *
	 * @return UserInfo
	 */
	public static function newAnonymous() {
		return new self( null, true );
	}

	/**
	 * Create an instance for a logged-in user by ID
	 * @param int $id User ID
	 * @param bool $verified True if the user is verified
	 * @return UserInfo
	 */
	public static function newFromId( $id, $verified = false ) {
		$user = User::newFromId( $id );

		// Ensure the ID actually exists
		$user->load();
		if ( $user->isAnon() ) {
			throw new \InvalidArgumentException( 'Invalid ID' );
		}

		return new self( $user, $verified );
	}

	/**
	 * Create an instance for a logged-in user by name
	 * @param string $name User name (need not exist locally)
	 * @param bool $verified True if the user is verified
	 * @return UserInfo
	 */
	public static function newFromName( $name, $verified = false ) {
		$user = User::newFromName( $name, 'usable' );
		if ( !$user ) {
			throw new \InvalidArgumentException( 'Invalid user name' );
		}
		return new self( $user, $verified );
	}

	/**
	 * Create an instance from an existing User object
	 * @param User $user (need not exist locally)
	 * @param bool $verified True if the user is verified
	 * @return UserInfo
	 */
	public static function newFromUser( User $user, $verified = false ) {
		return new self( $user, $verified );
	}

	/**
	 * Return whether this is an anonymous user
	 * @return bool
	 */
	public function isAnon() {
		return $this->user === null;
	}

	/**
	 * Return whether this represents a verified user
	 * @return bool
	 */
	public function isVerified() {
		return $this->verified;
	}

	/**
	 * Return the user ID
	 * @note Do not use this to test for anonymous users!
	 * @return int
	 */
	public function getId() {
		return $this->user === null ? 0 : $this->user->getId();
	}

	/**
	 * Return the user name
	 * @return string|null
	 */
	public function getName() {
		return $this->user === null ? null : $this->user->getName();
	}

	/**
	 * Return the user token
	 * @return string
	 */
	public function getToken() {
		return $this->user === null || $this->user->getId() === 0 ? '' : $this->user->getToken( false );
	}

	/**
	 * Return a User object
	 * @return User
	 */
	public function getUser() {
		return $this->user === null ? new User : $this->user;
	}

	/**
	 * Return a verified version of this object
	 * @return UserInfo
	 */
	public function verified() {
		return $this->verified ? $this : new self( $this->user, true );
	}

	public function __toString() {
		if ( $this->user === null ) {
			return '<anon>';
		}
		return '<' .
			( $this->verified ? '+' : '-' ) . ':' .
			$this->getId() . ':' . $this->getName() .
			'>';
	}

}