Merge "Highlight new requirement"
[lhc/web/wiklou.git] / tests / phpunit / includes / auth / AbstractPrimaryAuthenticationProviderTest.php
1 <?php
2
3 namespace MediaWiki\Auth;
4
5 /**
6 * @group AuthManager
7 * @covers MediaWiki\Auth\AbstractPrimaryAuthenticationProvider
8 */
9 class AbstractPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
10 protected function setUp() {
11 global $wgDisableAuthManager;
12
13 parent::setUp();
14 if ( $wgDisableAuthManager ) {
15 $this->markTestSkipped( '$wgDisableAuthManager is set' );
16 }
17 }
18
19 public function testAbstractPrimaryAuthenticationProvider() {
20 $user = \User::newFromName( 'UTSysop' );
21
22 $provider = $this->getMockForAbstractClass( AbstractPrimaryAuthenticationProvider::class );
23
24 try {
25 $provider->continuePrimaryAuthentication( [] );
26 $this->fail( 'Expected exception not thrown' );
27 } catch ( \BadMethodCallException $ex ) {
28 }
29
30 try {
31 $provider->continuePrimaryAccountCreation( $user, $user, [] );
32 $this->fail( 'Expected exception not thrown' );
33 } catch ( \BadMethodCallException $ex ) {
34 }
35
36 $req = $this->getMockForAbstractClass( AuthenticationRequest::class );
37
38 $this->assertTrue( $provider->providerAllowsPropertyChange( 'foo' ) );
39 $this->assertEquals(
40 \StatusValue::newGood(),
41 $provider->testForAccountCreation( $user, $user, [] )
42 );
43 $this->assertEquals(
44 \StatusValue::newGood(),
45 $provider->testUserForCreation( $user, AuthManager::AUTOCREATE_SOURCE_SESSION )
46 );
47 $this->assertEquals(
48 \StatusValue::newGood(),
49 $provider->testUserForCreation( $user, false )
50 );
51
52 $this->assertNull(
53 $provider->finishAccountCreation( $user, $user, AuthenticationResponse::newPass() )
54 );
55 $provider->autoCreatedAccount( $user, AuthManager::AUTOCREATE_SOURCE_SESSION );
56
57 $res = AuthenticationResponse::newPass();
58 $provider->postAuthentication( $user, $res );
59 $provider->postAccountCreation( $user, $user, $res );
60 $provider->postAccountLink( $user, $res );
61
62 $provider->expects( $this->once() )
63 ->method( 'testUserExists' )
64 ->with( $this->equalTo( 'foo' ) )
65 ->will( $this->returnValue( true ) );
66 $this->assertTrue( $provider->testUserCanAuthenticate( 'foo' ) );
67 }
68
69 public function testProviderRevokeAccessForUser() {
70 $reqs = [];
71 for ( $i = 0; $i < 3; $i++ ) {
72 $reqs[$i] = $this->getMock( AuthenticationRequest::class );
73 $reqs[$i]->done = false;
74 }
75
76 $provider = $this->getMockForAbstractClass( AbstractPrimaryAuthenticationProvider::class );
77 $provider->expects( $this->once() )->method( 'getAuthenticationRequests' )
78 ->with(
79 $this->identicalTo( AuthManager::ACTION_REMOVE ),
80 $this->identicalTo( [ 'username' => 'UTSysop' ] )
81 )
82 ->will( $this->returnValue( $reqs ) );
83 $provider->expects( $this->exactly( 3 ) )->method( 'providerChangeAuthenticationData' )
84 ->will( $this->returnCallback( function ( $req ) {
85 $this->assertSame( 'UTSysop', $req->username );
86 $this->assertFalse( $req->done );
87 $req->done = true;
88 } ) );
89
90 $provider->providerRevokeAccessForUser( 'UTSysop' );
91
92 foreach ( $reqs as $i => $req ) {
93 $this->assertTrue( $req->done, "#$i" );
94 }
95 }
96
97 /**
98 * @dataProvider providePrimaryAccountLink
99 * @param string $type PrimaryAuthenticationProvider::TYPE_* constant
100 * @param string $msg Error message from beginPrimaryAccountLink
101 */
102 public function testPrimaryAccountLink( $type, $msg ) {
103 $provider = $this->getMockForAbstractClass( AbstractPrimaryAuthenticationProvider::class );
104 $provider->expects( $this->any() )->method( 'accountCreationType' )
105 ->will( $this->returnValue( $type ) );
106
107 $class = AbstractPrimaryAuthenticationProvider::class;
108 $msg1 = "{$class}::beginPrimaryAccountLink $msg";
109 $msg2 = "{$class}::continuePrimaryAccountLink is not implemented.";
110
111 $user = \User::newFromName( 'Whatever' );
112
113 try {
114 $provider->beginPrimaryAccountLink( $user, [] );
115 $this->fail( 'Expected exception not thrown' );
116 } catch ( \BadMethodCallException $ex ) {
117 $this->assertSame( $msg1, $ex->getMessage() );
118 }
119 try {
120 $provider->continuePrimaryAccountLink( $user, [] );
121 $this->fail( 'Expected exception not thrown' );
122 } catch ( \BadMethodCallException $ex ) {
123 $this->assertSame( $msg2, $ex->getMessage() );
124 }
125 }
126
127 public static function providePrimaryAccountLink() {
128 return [
129 [
130 PrimaryAuthenticationProvider::TYPE_NONE,
131 'should not be called on a non-link provider.',
132 ],
133 [
134 PrimaryAuthenticationProvider::TYPE_CREATE,
135 'should not be called on a non-link provider.',
136 ],
137 [
138 PrimaryAuthenticationProvider::TYPE_LINK,
139 'is not implemented.',
140 ],
141 ];
142 }
143
144 /**
145 * @dataProvider provideProviderNormalizeUsername
146 */
147 public function testProviderNormalizeUsername( $name, $expect ) {
148 // fake interwiki map for the 'Interwiki prefix' testcase
149 $this->mergeMwGlobalArrayValue( 'wgHooks', [
150 'InterwikiLoadPrefix' => [
151 function ( $prefix, &$iwdata ) {
152 if ( $prefix === 'interwiki' ) {
153 $iwdata = [
154 'iw_url' => 'http://example.com/',
155 'iw_local' => 0,
156 'iw_trans' => 0,
157 ];
158 return false;
159 }
160 },
161 ],
162 ] );
163
164 $provider = $this->getMockForAbstractClass( AbstractPrimaryAuthenticationProvider::class );
165 $this->assertSame( $expect, $provider->providerNormalizeUsername( $name ) );
166 }
167
168 public static function provideProviderNormalizeUsername() {
169 return [
170 'Leading space' => [ ' Leading space', 'Leading space' ],
171 'Trailing space ' => [ 'Trailing space ', 'Trailing space' ],
172 'Namespace prefix' => [ 'Talk:Username', null ],
173 'Interwiki prefix' => [ 'interwiki:Username', null ],
174 'With hash' => [ 'name with # hash', null ],
175 'Multi spaces' => [ 'Multi spaces', 'Multi spaces' ],
176 'Lowercase' => [ 'lowercase', 'Lowercase' ],
177 'Invalid character' => [ 'in[]valid', null ],
178 'With slash' => [ 'with / slash', null ],
179 'Underscores' => [ '___under__scores___', 'Under scores' ],
180 ];
181 }
182
183 }