Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
33 / 33 |
|
100.00% |
13 / 13 |
CRAP | |
100.00% |
1 / 1 |
UserInfo | |
100.00% |
33 / 33 |
|
100.00% |
13 / 13 |
25 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
newAnonymous | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newFromId | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
newFromName | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
newFromUser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isAnon | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isVerified | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getName | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getToken | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
3 | |||
getUser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
verified | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
__toString | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | /** |
3 | * MediaWiki session user info |
4 | * |
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. |
9 | * |
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. |
14 | * |
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 |
19 | * |
20 | * @file |
21 | * @ingroup Session |
22 | */ |
23 | |
24 | namespace MediaWiki\Session; |
25 | |
26 | use InvalidArgumentException; |
27 | use MediaWiki\MediaWikiServices; |
28 | use MediaWiki\User\User; |
29 | use MediaWiki\User\UserRigorOptions; |
30 | use Stringable; |
31 | |
32 | /** |
33 | * Object holding data about a session's user |
34 | * |
35 | * In general, this class exists for two purposes: |
36 | * - User doesn't distinguish between "anonymous user" and "non-anonymous user |
37 | * that doesn't exist locally", while we do need to. |
38 | * - We also need the "verified" property described below; tracking it via |
39 | * another data item to SessionInfo's constructor makes things much more |
40 | * confusing. |
41 | * |
42 | * A UserInfo may be "verified". This indicates that the creator knows that the |
43 | * request really comes from that user, whether that's by validating OAuth |
44 | * credentials, SSL client certificates, or by having both the user ID and |
45 | * token available from cookies. |
46 | * |
47 | * An "unverified" UserInfo should be used when it's not possible to |
48 | * authenticate the user, e.g. the user ID cookie is set but the user Token |
49 | * cookie isn't. If the Token is available but doesn't match, don't return a |
50 | * UserInfo at all. |
51 | * |
52 | * @ingroup Session |
53 | * @since 1.27 |
54 | */ |
55 | final class UserInfo implements Stringable { |
56 | /** @var bool */ |
57 | private $verified = false; |
58 | |
59 | /** @var User|null */ |
60 | private $user = null; |
61 | |
62 | private function __construct( ?User $user, $verified ) { |
63 | $userNameUtils = MediaWikiServices::getInstance()->getUserNameUtils(); |
64 | if ( $user && $user->isAnon() && !$userNameUtils->isUsable( $user->getName() ) ) { |
65 | $this->verified = true; |
66 | $this->user = null; |
67 | } else { |
68 | $this->verified = $verified; |
69 | $this->user = $user; |
70 | } |
71 | } |
72 | |
73 | /** |
74 | * Create an instance for an anonymous (i.e. not logged in) user |
75 | * |
76 | * Logged-out users are always "verified". |
77 | * |
78 | * @return UserInfo |
79 | */ |
80 | public static function newAnonymous() { |
81 | return new self( null, true ); |
82 | } |
83 | |
84 | /** |
85 | * Create an instance for a logged-in user by ID |
86 | * @param int $id User ID |
87 | * @param bool $verified True if the user is verified |
88 | * @return UserInfo |
89 | */ |
90 | public static function newFromId( $id, $verified = false ) { |
91 | $user = MediaWikiServices::getInstance()->getUserFactory()->newFromId( (int)$id ); |
92 | |
93 | // Ensure the ID actually exists |
94 | $user->load(); |
95 | if ( $user->isAnon() ) { |
96 | throw new InvalidArgumentException( 'Invalid ID' ); |
97 | } |
98 | |
99 | return new self( $user, $verified ); |
100 | } |
101 | |
102 | /** |
103 | * Create an instance for a logged-in user by name |
104 | * @param string $name User name (need not exist locally) |
105 | * @param bool $verified True if the user is verified |
106 | * @return UserInfo |
107 | */ |
108 | public static function newFromName( $name, $verified = false ) { |
109 | $user = MediaWikiServices::getInstance()->getUserFactory()->newFromName( |
110 | (string)$name, |
111 | UserRigorOptions::RIGOR_USABLE |
112 | ); |
113 | if ( !$user ) { |
114 | throw new InvalidArgumentException( 'Invalid user name' ); |
115 | } |
116 | return new self( $user, $verified ); |
117 | } |
118 | |
119 | /** |
120 | * Create an instance from an existing User object |
121 | * @param User $user (need not exist locally) |
122 | * @param bool $verified True if the user is verified |
123 | * @return UserInfo |
124 | */ |
125 | public static function newFromUser( User $user, $verified = false ) { |
126 | return new self( $user, $verified ); |
127 | } |
128 | |
129 | /** |
130 | * Return whether this is an anonymous user |
131 | * @return bool |
132 | */ |
133 | public function isAnon() { |
134 | return $this->user === null; |
135 | } |
136 | |
137 | /** |
138 | * Return whether this represents a verified user |
139 | * @return bool |
140 | */ |
141 | public function isVerified() { |
142 | return $this->verified; |
143 | } |
144 | |
145 | /** |
146 | * Return the user ID |
147 | * @note Do not use this to test for anonymous users! |
148 | * @return int |
149 | */ |
150 | public function getId() { |
151 | return $this->user === null ? 0 : $this->user->getId(); |
152 | } |
153 | |
154 | /** |
155 | * Return the user name |
156 | * @return string|null |
157 | */ |
158 | public function getName() { |
159 | return $this->user === null ? null : $this->user->getName(); |
160 | } |
161 | |
162 | /** |
163 | * Return the user token |
164 | * @return string |
165 | */ |
166 | public function getToken() { |
167 | return $this->user === null || $this->user->getId() === 0 ? '' : $this->user->getToken( false ); |
168 | } |
169 | |
170 | /** |
171 | * Return a User object |
172 | * @return User |
173 | */ |
174 | public function getUser() { |
175 | return $this->user ?? MediaWikiServices::getInstance()->getUserFactory()->newAnonymous(); |
176 | } |
177 | |
178 | /** |
179 | * Return a verified version of this object |
180 | * @return UserInfo |
181 | */ |
182 | public function verified() { |
183 | return $this->verified ? $this : new self( $this->user, true ); |
184 | } |
185 | |
186 | public function __toString() { |
187 | if ( $this->user === null ) { |
188 | return '<anon>'; |
189 | } |
190 | return '<' . |
191 | ( $this->verified ? '+' : '-' ) . ':' . |
192 | $this->getId() . ':' . $this->getName() . |
193 | '>'; |
194 | } |
195 | |
196 | } |